diff --git a/shared-infrastructure b/shared-infrastructure index bf398a9b6b..47ff841e1d 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit bf398a9b6bb6d0acfe0525ee109276b4ef74646c +Subproject commit 47ff841e1d2226a0fc5953e3d79ab6c9f6a24a46 diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs index 10267c8ef7..f0d71f212d 100644 --- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs +++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs @@ -27,7 +27,7 @@ public static IImageEncoder DetectEncoder(this Image source, string filePath) Guard.NotNull(filePath, nameof(filePath)); string ext = Path.GetExtension(filePath); - IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext); + IImageFormat? format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext); if (format is null) { StringBuilder sb = new(); @@ -40,7 +40,7 @@ public static IImageEncoder DetectEncoder(this Image source, string filePath) throw new NotSupportedException(sb.ToString()); } - IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); + IImageEncoder? encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); if (encoder is null) { @@ -99,7 +99,7 @@ public static Configuration GetConfiguration(this ImageFrame source) /// The source image /// Returns the bounds of the image private static Configuration GetConfiguration(IConfigurationProvider source) - => source?.Configuration ?? Configuration.Default; + => source.Configuration ?? Configuration.Default; /// /// Gets the representation of the pixels as a containing the backing pixel data of the image @@ -115,7 +115,7 @@ private static Configuration GetConfiguration(IConfigurationProvider source) /// Thrown when the in . public static IMemoryGroup GetPixelMemoryGroup(this ImageFrame source) where TPixel : unmanaged, IPixel - => source?.PixelBuffer.FastMemoryGroup.View ?? throw new ArgumentNullException(nameof(source)); + => source.PixelBuffer!.FastMemoryGroup.View ?? throw new ArgumentNullException(nameof(source)); /// /// Gets the representation of the pixels as a containing the backing pixel data of the image @@ -131,7 +131,7 @@ public static IMemoryGroup GetPixelMemoryGroup(this ImageFrameThrown when the in . public static IMemoryGroup GetPixelMemoryGroup(this Image source) where TPixel : unmanaged, IPixel - => source?.Frames.RootFrame.GetPixelMemoryGroup() ?? throw new ArgumentNullException(nameof(source)); + => source.Frames.RootFrame.GetPixelMemoryGroup() ?? throw new ArgumentNullException(nameof(source)); /// /// Gets the representation of the pixels as a of contiguous memory @@ -148,7 +148,7 @@ public static Memory DangerousGetPixelRowMemory(this ImageFrame< Guard.MustBeGreaterThanOrEqualTo(rowIndex, 0, nameof(rowIndex)); Guard.MustBeLessThan(rowIndex, source.Height, nameof(rowIndex)); - return source.PixelBuffer.GetSafeRowMemory(rowIndex); + return source.PixelBuffer!.GetSafeRowMemory(rowIndex); } /// @@ -166,7 +166,7 @@ public static Memory DangerousGetPixelRowMemory(this Image diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 9c285e21de..223b7d275a 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +#nullable disable using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; diff --git a/src/ImageSharp/Advanced/IConfigurationProvider.cs b/src/ImageSharp/Advanced/IConfigurationProvider.cs index 086461f448..1191c9bdfa 100644 --- a/src/ImageSharp/Advanced/IConfigurationProvider.cs +++ b/src/ImageSharp/Advanced/IConfigurationProvider.cs @@ -11,5 +11,5 @@ internal interface IConfigurationProvider /// /// Gets the configuration which allows altering default behaviour or extending the library. /// - Configuration Configuration { get; } + Configuration? Configuration { get; } } diff --git a/src/ImageSharp/Advanced/IPixelSource.cs b/src/ImageSharp/Advanced/IPixelSource.cs index a46f7d4080..93d5467ffd 100644 --- a/src/ImageSharp/Advanced/IPixelSource.cs +++ b/src/ImageSharp/Advanced/IPixelSource.cs @@ -27,5 +27,5 @@ internal interface IPixelSource /// /// Gets the pixel buffer. /// - Buffer2D PixelBuffer { get; } + Buffer2D? PixelBuffer { get; } } diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index 28dc1cf924..99a271bcf7 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp; public readonly partial struct Color : IEquatable { private readonly Rgba64 data; - private readonly IPixel boxedHighPrecisionPixel; + private readonly IPixel? boxedHighPrecisionPixel; [MethodImpl(InliningOptions.ShortMethod)] private Color(byte r, byte g, byte b, byte a) @@ -316,7 +316,7 @@ public bool Equals(Color other) } /// - public override bool Equals(object obj) => obj is Color other && this.Equals(other); + public override bool Equals(object? obj) => obj is Color other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/CieLab.cs b/src/ImageSharp/ColorSpaces/CieLab.cs index 35b664e8a3..2346b395c0 100644 --- a/src/ImageSharp/ColorSpaces/CieLab.cs +++ b/src/ImageSharp/ColorSpaces/CieLab.cs @@ -123,7 +123,7 @@ public CieLab(Vector3 vector, CieXyz whitePoint) public override string ToString() => FormattableString.Invariant($"CieLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})"); /// - public override bool Equals(object obj) => obj is CieLab other && this.Equals(other); + public override bool Equals(object? obj) => obj is CieLab other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs index e6f53cbb42..48e8e2c6d9 100644 --- a/src/ImageSharp/ColorSpaces/CieLch.cs +++ b/src/ImageSharp/ColorSpaces/CieLch.cs @@ -127,7 +127,7 @@ public override int GetHashCode() /// [MethodImpl(InliningOptions.ShortMethod)] - public override bool Equals(object obj) => obj is CieLch other && this.Equals(other); + public override bool Equals(object? obj) => obj is CieLch other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/CieLchuv.cs b/src/ImageSharp/ColorSpaces/CieLchuv.cs index de669e7ed9..4d47be5aa3 100644 --- a/src/ImageSharp/ColorSpaces/CieLchuv.cs +++ b/src/ImageSharp/ColorSpaces/CieLchuv.cs @@ -124,7 +124,7 @@ public CieLchuv(Vector3 vector, CieXyz whitePoint) public override string ToString() => FormattableString.Invariant($"CieLchuv({this.L:#0.##}, {this.C:#0.##}, {this.H:#0.##})"); /// - public override bool Equals(object obj) => obj is CieLchuv other && this.Equals(other); + public override bool Equals(object? obj) => obj is CieLchuv other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/CieLuv.cs b/src/ImageSharp/ColorSpaces/CieLuv.cs index f4de5198e0..04bc96cfa2 100644 --- a/src/ImageSharp/ColorSpaces/CieLuv.cs +++ b/src/ImageSharp/ColorSpaces/CieLuv.cs @@ -124,7 +124,7 @@ public CieLuv(Vector3 vector, CieXyz whitePoint) public override string ToString() => FormattableString.Invariant($"CieLuv({this.L:#0.##}, {this.U:#0.##}, {this.V:#0.##})"); /// - public override bool Equals(object obj) => obj is CieLuv other && this.Equals(other); + public override bool Equals(object? obj) => obj is CieLuv other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/CieXyy.cs b/src/ImageSharp/ColorSpaces/CieXyy.cs index 2e725a5011..6b7d2e6cbd 100644 --- a/src/ImageSharp/ColorSpaces/CieXyy.cs +++ b/src/ImageSharp/ColorSpaces/CieXyy.cs @@ -88,7 +88,7 @@ public CieXyy(Vector3 vector) public override string ToString() => FormattableString.Invariant($"CieXyy({this.X:#0.##}, {this.Y:#0.##}, {this.Yl:#0.##})"); /// - public override bool Equals(object obj) => obj is CieXyy other && this.Equals(other); + public override bool Equals(object? obj) => obj is CieXyy other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs index 53d93c32b8..2ac9c9f286 100644 --- a/src/ImageSharp/ColorSpaces/CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/CieXyz.cs @@ -91,7 +91,7 @@ public CieXyz(Vector3 vector) public override string ToString() => FormattableString.Invariant($"CieXyz({this.X:#0.##}, {this.Y:#0.##}, {this.Z:#0.##})"); /// - public override bool Equals(object obj) => obj is CieXyz other && this.Equals(other); + public override bool Equals(object? obj) => obj is CieXyz other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs index 615b6d34dc..a5aacf38ad 100644 --- a/src/ImageSharp/ColorSpaces/Cmyk.cs +++ b/src/ImageSharp/ColorSpaces/Cmyk.cs @@ -95,7 +95,7 @@ public Cmyk(Vector4 vector) public override string ToString() => FormattableString.Invariant($"Cmyk({this.C:#0.##}, {this.M:#0.##}, {this.Y:#0.##}, {this.K:#0.##})"); /// - public override bool Equals(object obj) => obj is Cmyk other && this.Equals(other); + public override bool Equals(object? obj) => obj is Cmyk other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs index 52a9ef27ee..f4f0ed35d0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs @@ -32,7 +32,7 @@ public CieXyz Adapt(in CieXyz color, in CieXyz sourceWhitePoint, in CieXyz targe return color; } - return this.chromaticAdaptation.Transform(color, sourceWhitePoint, targetWhitePoint); + return this.chromaticAdaptation!.Transform(color, sourceWhitePoint, targetWhitePoint); } /// @@ -132,7 +132,7 @@ public LinearRgb Adapt(in LinearRgb color) CieXyz unadapted = converterToXYZ.Convert(color); // Adaptation - CieXyz adapted = this.chromaticAdaptation.Transform(unadapted, color.WorkingSpace.WhitePoint, this.targetRgbWorkingSpace.WhitePoint); + CieXyz adapted = this.chromaticAdaptation!.Transform(unadapted, color.WorkingSpace.WhitePoint, this.targetRgbWorkingSpace.WhitePoint); // Conversion back to RGB return this.cieXyzToLinearRgbConverter.Convert(adapted); diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs index ac1fa8ed0a..65298597c3 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs @@ -13,7 +13,7 @@ public partial class ColorSpaceConverter { private static readonly HunterLabToCieXyzConverter HunterLabToCieXyzConverter = new(); - private LinearRgbToCieXyzConverter linearRgbToCieXyzConverter; + private LinearRgbToCieXyzConverter? linearRgbToCieXyzConverter; /// /// Converts a into a . diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs index fbe441a8c7..9aecf7dbed 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs @@ -18,7 +18,7 @@ public partial class ColorSpaceConverter private readonly CieXyz targetLabWhitePoint; private readonly CieXyz targetHunterLabWhitePoint; private readonly RgbWorkingSpace targetRgbWorkingSpace; - private readonly IChromaticAdaptation chromaticAdaptation; + private readonly IChromaticAdaptation? chromaticAdaptation; private readonly bool performChromaticAdaptation; private readonly CieXyzAndLmsConverter cieXyzAndLmsConverter; private readonly CieXyzToCieLabConverter cieXyzToCieLabConverter; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs index abcff202f5..2cc785d53b 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/CieXyChromaticityCoordinates.cs @@ -73,7 +73,7 @@ public override string ToString() => FormattableString.Invariant($"CieXyChromaticityCoordinates({this.X:#0.##}, {this.Y:#0.##})"); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is CieXyChromaticityCoordinates other && this.Equals(other); /// diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs index 9dace7c41d..625e6c551a 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs @@ -72,7 +72,7 @@ public RgbPrimariesChromaticityCoordinates(CieXyChromaticityCoordinates r, CieXy } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is RgbPrimariesChromaticityCoordinates other && this.Equals(other); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs index 87b0ce8065..e95f1f2b47 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs @@ -34,7 +34,7 @@ public GammaWorkingSpace(float gamma, CieXyz referenceWhite, RgbPrimariesChromat public override float Expand(float channel) => GammaCompanding.Expand(channel, this.Gamma); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is null) { diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs index 44893e19da..f22f2ff1fa 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs @@ -52,7 +52,7 @@ protected RgbWorkingSpace(CieXyz referenceWhite, RgbPrimariesChromaticityCoordin public abstract float Compress(float channel); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is null) { diff --git a/src/ImageSharp/ColorSpaces/Hsl.cs b/src/ImageSharp/ColorSpaces/Hsl.cs index e34a7945a9..cf18c70c78 100644 --- a/src/ImageSharp/ColorSpaces/Hsl.cs +++ b/src/ImageSharp/ColorSpaces/Hsl.cs @@ -89,7 +89,7 @@ public Hsl(Vector3 vector) public override string ToString() => FormattableString.Invariant($"Hsl({this.H:#0.##}, {this.S:#0.##}, {this.L:#0.##})"); /// - public override bool Equals(object obj) => obj is Hsl other && this.Equals(other); + public override bool Equals(object? obj) => obj is Hsl other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/Hsv.cs b/src/ImageSharp/ColorSpaces/Hsv.cs index 501d421e5e..87c16c0b6a 100644 --- a/src/ImageSharp/ColorSpaces/Hsv.cs +++ b/src/ImageSharp/ColorSpaces/Hsv.cs @@ -87,7 +87,7 @@ public Hsv(Vector3 vector) public override string ToString() => FormattableString.Invariant($"Hsv({this.H:#0.##}, {this.S:#0.##}, {this.V:#0.##})"); /// - public override bool Equals(object obj) => obj is Hsv other && this.Equals(other); + public override bool Equals(object? obj) => obj is Hsv other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs index a1039b2359..516574b098 100644 --- a/src/ImageSharp/ColorSpaces/HunterLab.cs +++ b/src/ImageSharp/ColorSpaces/HunterLab.cs @@ -122,7 +122,7 @@ public HunterLab(Vector3 vector, CieXyz whitePoint) public override string ToString() => FormattableString.Invariant($"HunterLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})"); /// - public override bool Equals(object obj) => obj is HunterLab other && this.Equals(other); + public override bool Equals(object? obj) => obj is HunterLab other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs index 52daf5d521..49c7814a0e 100644 --- a/src/ImageSharp/ColorSpaces/LinearRgb.cs +++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs @@ -131,7 +131,7 @@ public LinearRgb(Vector3 vector, RgbWorkingSpace workingSpace) public override string ToString() => FormattableString.Invariant($"LinearRgb({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##})"); /// - public override bool Equals(object obj) => obj is LinearRgb other && this.Equals(other); + public override bool Equals(object? obj) => obj is LinearRgb other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/Lms.cs b/src/ImageSharp/ColorSpaces/Lms.cs index 5a1727addb..99210ff6e4 100644 --- a/src/ImageSharp/ColorSpaces/Lms.cs +++ b/src/ImageSharp/ColorSpaces/Lms.cs @@ -92,7 +92,7 @@ public Lms(Vector3 vector) public override string ToString() => FormattableString.Invariant($"Lms({this.L:#0.##}, {this.M:#0.##}, {this.S:#0.##})"); /// - public override bool Equals(object obj) => obj is Lms other && this.Equals(other); + public override bool Equals(object? obj) => obj is Lms other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs index b70d96b647..55052a710e 100644 --- a/src/ImageSharp/ColorSpaces/Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Rgb.cs @@ -152,7 +152,7 @@ public Rgb(Vector3 vector, RgbWorkingSpace workingSpace) public override string ToString() => FormattableString.Invariant($"Rgb({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##})"); /// - public override bool Equals(object obj) => obj is Rgb other && this.Equals(other); + public override bool Equals(object? obj) => obj is Rgb other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs index 459063fffa..acb59388fb 100644 --- a/src/ImageSharp/ColorSpaces/YCbCr.cs +++ b/src/ImageSharp/ColorSpaces/YCbCr.cs @@ -88,7 +88,7 @@ public YCbCr(Vector3 vector) public override string ToString() => FormattableString.Invariant($"YCbCr({this.Y}, {this.Cb}, {this.Cr})"); /// - public override bool Equals(object obj) => obj is YCbCr other && this.Equals(other); + public override bool Equals(object? obj) => obj is YCbCr other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs index cc10c6e00a..c2c4308ad3 100644 --- a/src/ImageSharp/Common/Helpers/Guard.cs +++ b/src/ImageSharp/Common/Helpers/Guard.cs @@ -17,6 +17,7 @@ internal static partial class Guard /// is not a value type. [MethodImpl(InliningOptions.ShortMethod)] public static void MustBeValueType(TValue value, string parameterName) + where TValue : class { if (value.GetType().IsValueType) { diff --git a/src/ImageSharp/Common/Helpers/UnitConverter.cs b/src/ImageSharp/Common/Helpers/UnitConverter.cs index 04ecb5afd0..983d86a711 100644 --- a/src/ImageSharp/Common/Helpers/UnitConverter.cs +++ b/src/ImageSharp/Common/Helpers/UnitConverter.cs @@ -91,7 +91,7 @@ internal static class UnitConverter [MethodImpl(InliningOptions.ShortMethod)] public static PixelResolutionUnit ExifProfileToResolutionUnit(ExifProfile profile) { - IExifValue resolution = profile.GetValue(ExifTag.ResolutionUnit); + IExifValue? resolution = profile.GetValue(ExifTag.ResolutionUnit); // EXIF is 1, 2, 3 so we minus "1" off the result. return resolution is null ? DefaultResolutionUnit : (PixelResolutionUnit)(byte)(resolution.Value - 1); diff --git a/src/ImageSharp/Compression/Zlib/Deflater.cs b/src/ImageSharp/Compression/Zlib/Deflater.cs index 78da8e8afe..f642ec85a7 100644 --- a/src/ImageSharp/Compression/Zlib/Deflater.cs +++ b/src/ImageSharp/Compression/Zlib/Deflater.cs @@ -284,7 +284,6 @@ public void Dispose() if (!this.isDisposed) { this.engine.Dispose(); - this.engine = null; this.isDisposed = true; } } diff --git a/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs b/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs index 2fc1d2743e..ec0f45abfd 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs @@ -86,7 +86,7 @@ internal sealed unsafe class DeflaterEngine : IDisposable /// /// The input data for compression. /// - private byte[] inputBuf; + private byte[]? inputBuf; /// /// The offset into inputBuf, where input data starts. @@ -221,12 +221,9 @@ public bool Deflate(bool flush, bool finish) /// The buffer containing input data. /// The offset of the first byte of data. /// The number of bytes of data to use as input. - public void SetInput(byte[] buffer, int offset, int count) + public void SetInput(byte[]? buffer, int offset, int count) { - if (buffer is null) - { - DeflateThrowHelper.ThrowNull(nameof(buffer)); - } + ArgumentNullException.ThrowIfNull(buffer); if (offset < 0) { @@ -342,7 +339,7 @@ public void SetLevel(int level) /// /// Fill the window /// - public void FillWindow() + private void FillWindow() { // If the window is almost full and there is insufficient lookahead, // move the upper half to the lower one to make room in the upper half. @@ -361,6 +358,8 @@ public void FillWindow() more = this.inputEnd - this.inputOff; } + ArgumentNullException.ThrowIfNull(this.inputBuf); + Unsafe.CopyBlockUnaligned( ref this.window.Span[this.strstart + this.lookahead], ref this.inputBuf[this.inputOff], @@ -392,11 +391,6 @@ public void Dispose() this.prevMemoryHandle.Dispose(); this.prevMemoryOwner.Dispose(); - this.windowMemoryOwner = null; - this.headMemoryOwner = null; - this.prevMemoryOwner = null; - this.huffman = null; - this.isDisposed = true; } } diff --git a/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs b/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs index 34058b43a8..dc11de4259 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs @@ -426,10 +426,6 @@ public void Dispose() this.blTree.Dispose(); this.distTree.Dispose(); - this.Pending = null; - this.literalTree = null; - this.blTree = null; - this.distTree = null; this.isDisposed = true; } } @@ -976,10 +972,6 @@ public void Dispose() this.codesMemoryHandle.Dispose(); this.codesMemoryOwner.Dispose(); - this.frequenciesMemoryOwner = null; - this.lengthsMemoryOwner = null; - this.codesMemoryOwner = null; - this.isDisposed = true; } } diff --git a/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs b/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs index 6d7903caa1..de818fd8f5 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs @@ -136,8 +136,6 @@ protected override void Dispose(bool disposing) this.memoryOwner.Dispose(); } - this.deflater = null; - this.memoryOwner = null; this.isDisposed = true; base.Dispose(disposing); } diff --git a/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs b/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs index d2e0e27943..37e7404e40 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs @@ -179,7 +179,6 @@ public void Dispose() { this.bufferMemoryHandle.Dispose(); this.bufferMemoryOwner.Dispose(); - this.bufferMemoryOwner = null; this.isDisposed = true; } } diff --git a/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs b/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs index b46283534d..2e52f84d7b 100644 --- a/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs +++ b/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs @@ -171,8 +171,6 @@ protected override void Dispose(bool disposing) this.rawStream.WriteByte((byte)(crc & 0xFF)); } - this.deflateStream = null; - base.Dispose(disposing); this.isDisposed = true; } diff --git a/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs b/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs index 410333dc48..66af8be78b 100644 --- a/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs +++ b/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs @@ -89,7 +89,7 @@ public ZlibInflateStream(BufferedReadStream innerStream, Func getData) /// /// Gets the compressed stream over the deframed inner stream. /// - public DeflateStream CompressedStream { get; private set; } + public DeflateStream? CompressedStream { get; private set; } /// /// Adds new bytes from a frame found in the original stream. diff --git a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs index b66cede3a0..8327daf23b 100644 --- a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs +++ b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs @@ -16,7 +16,7 @@ public static class MemoryDiagnostics { private static int totalUndisposedAllocationCount; - private static UndisposedAllocationDelegate undisposedAllocation; + private static UndisposedAllocationDelegate? undisposedAllocation; private static int undisposedAllocationSubscriptionCounter; private static readonly object SyncRoot = new(); @@ -49,12 +49,12 @@ public static event UndisposedAllocationDelegate UndisposedAllocation /// /// Fires when ImageSharp allocates memory from a MemoryAllocator /// - internal static event Action MemoryAllocated; + internal static event Action? MemoryAllocated; /// /// Fires when ImageSharp releases memory allocated from a MemoryAllocator /// - internal static event Action MemoryReleased; + internal static event Action? MemoryReleased; /// /// Gets a value indicating the total number of memory resource objects leaked to the finalizer. diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs index 35d5690c7d..982dc37cc4 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoder.cs @@ -35,6 +35,8 @@ Image IImageDecoderSpecialized.Decode(BmpDeco Image image = new BmpDecoderCore(options).Decode(options.GeneralOptions.Configuration, stream, cancellationToken); + ArgumentNullException.ThrowIfNull(image); + ImageDecoderUtilities.Resize(options.GeneralOptions, image); return image; diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 1629d66843..a2ef44734a 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Common.Helpers; @@ -57,20 +58,15 @@ internal sealed class BmpDecoderCore : IImageDecoderInternals /// private const int RleDelta = 0x02; - /// - /// The stream to decode from. - /// - private BufferedReadStream stream; - /// /// The metadata. /// - private ImageMetadata metadata; + private ImageMetadata? metadata; /// /// The bitmap specific metadata. /// - private BmpMetadata bmpMetadata; + private BmpMetadata? bmpMetadata; /// /// The file header containing general information. @@ -119,13 +115,13 @@ public BmpDecoderCore(BmpDecoderOptions options) public DecoderOptions Options { get; } /// - public Size Dimensions => new(this.infoHeader.Width, this.infoHeader.Height); + public Size? Dimensions => new(this.infoHeader.Width, this.infoHeader.Height); /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { - Image image = null; + Image? image = null; try { int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette); @@ -141,24 +137,25 @@ public Image Decode(BufferedReadStream stream, CancellationToken { if (this.bmpMetadata.InfoHeaderType == BmpInfoHeaderType.WinVersion3) { - this.ReadRgb32Slow(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + this.ReadRgb32Slow(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); } else { - this.ReadRgb32Fast(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + this.ReadRgb32Fast(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); } } else if (this.infoHeader.BitsPerPixel == 24) { - this.ReadRgb24(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + this.ReadRgb24(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); } else if (this.infoHeader.BitsPerPixel == 16) { - this.ReadRgb16(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + this.ReadRgb16(stream, pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); } else if (this.infoHeader.BitsPerPixel <= 8) { this.ReadRgbPalette( + stream, pixels, palette, this.infoHeader.Width, @@ -171,19 +168,19 @@ public Image Decode(BufferedReadStream stream, CancellationToken break; case BmpCompression.RLE24: - this.ReadRle24(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted); + this.ReadRle24(pixels, this.infoHeader.Width, this.infoHeader.Height, inverted, stream); break; case BmpCompression.RLE8: case BmpCompression.RLE4: - this.ReadRle(this.infoHeader.Compression, pixels, palette, this.infoHeader.Width, this.infoHeader.Height, inverted); + this.ReadRle(this.infoHeader.Compression, pixels, palette, this.infoHeader.Width, this.infoHeader.Height, inverted, stream); break; case BmpCompression.BitFields: case BmpCompression.BI_ALPHABITFIELDS: - this.ReadBitFields(pixels, inverted); + this.ReadBitFields(stream, pixels, inverted); break; @@ -251,12 +248,13 @@ private static int CalculatePadding(int width, int componentCount) /// The pixel format. /// The output pixel buffer containing the decoded image. /// Whether the bitmap is inverted. - private void ReadBitFields(Buffer2D pixels, bool inverted) + private void ReadBitFields(BufferedReadStream stream, Buffer2D pixels, bool inverted) where TPixel : unmanaged, IPixel { if (this.infoHeader.BitsPerPixel == 16) { this.ReadRgb16( + stream, pixels, this.infoHeader.Width, this.infoHeader.Height, @@ -268,6 +266,7 @@ private void ReadBitFields(Buffer2D pixels, bool inverted) else { this.ReadRgb32BitFields( + stream, pixels, this.infoHeader.Width, this.infoHeader.Height, @@ -291,7 +290,7 @@ private void ReadBitFields(Buffer2D pixels, bool inverted) /// The width of the bitmap. /// The height of the bitmap. /// Whether the bitmap is inverted. - private void ReadRle(BmpCompression compression, Buffer2D pixels, byte[] colors, int width, int height, bool inverted) + private void ReadRle(BmpCompression compression, Buffer2D pixels, byte[] colors, int width, int height, bool inverted, BufferedReadStream stream) where TPixel : unmanaged, IPixel { TPixel color = default; @@ -304,11 +303,11 @@ private void ReadRle(BmpCompression compression, Buffer2D pixels Span bufferSpan = buffer.Memory.Span; if (compression is BmpCompression.RLE8) { - this.UncompressRle8(width, bufferSpan, undefinedPixelsSpan, rowsWithUndefinedPixelsSpan); + this.UncompressRle8(width, bufferSpan, undefinedPixelsSpan, rowsWithUndefinedPixelsSpan, stream); } else { - this.UncompressRle4(width, bufferSpan, undefinedPixelsSpan, rowsWithUndefinedPixelsSpan); + this.UncompressRle4(width, bufferSpan, undefinedPixelsSpan, rowsWithUndefinedPixelsSpan, stream); } for (int y = 0; y < height; y++) @@ -371,7 +370,7 @@ private void ReadRle(BmpCompression compression, Buffer2D pixels /// The width of the bitmap. /// The height of the bitmap. /// Whether the bitmap is inverted. - private void ReadRle24(Buffer2D pixels, int width, int height, bool inverted) + private void ReadRle24(Buffer2D pixels, int width, int height, bool inverted, BufferedReadStream stream) where TPixel : unmanaged, IPixel { TPixel color = default; @@ -383,7 +382,7 @@ private void ReadRle24(Buffer2D pixels, int width, int height, b Span undefinedPixelsSpan = undefinedPixels.Memory.Span; Span bufferSpan = buffer.GetSpan(); - this.UncompressRle24(width, bufferSpan, undefinedPixelsSpan, rowsWithUndefinedPixelsSpan); + this.UncompressRle24(width, bufferSpan, undefinedPixelsSpan, rowsWithUndefinedPixelsSpan, stream); for (int y = 0; y < height; y++) { int newY = Invert(y, height, inverted); @@ -449,14 +448,14 @@ private void ReadRle24(Buffer2D pixels, int width, int height, b /// Buffer for uncompressed data. /// Keeps track over skipped and therefore undefined pixels. /// Keeps track of rows, which have undefined pixels. - private void UncompressRle4(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels) + private void UncompressRle4(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels, BufferedReadStream stream) { Span cmd = stackalloc byte[2]; int count = 0; while (count < buffer.Length) { - if (this.stream.Read(cmd, 0, cmd.Length) != 2) + if (stream.Read(cmd, 0, cmd.Length) != 2) { BmpThrowHelper.ThrowInvalidImageContentException("Failed to read 2 bytes from the stream while uncompressing RLE4 bitmap."); } @@ -477,8 +476,8 @@ private void UncompressRle4(int w, Span buffer, Span undefinedPixels break; case RleDelta: - int dx = this.stream.ReadByte(); - int dy = this.stream.ReadByte(); + int dx = stream.ReadByte(); + int dy = stream.ReadByte(); count += RleSkipDelta(count, w, dx, dy, undefinedPixels, rowsWithUndefinedPixels); break; @@ -491,7 +490,7 @@ private void UncompressRle4(int w, Span buffer, Span undefinedPixels byte[] run = new byte[bytesToRead]; - this.stream.Read(run, 0, run.Length); + stream.Read(run, 0, run.Length); int idx = 0; for (int i = 0; i < max; i++) @@ -511,7 +510,7 @@ private void UncompressRle4(int w, Span buffer, Span undefinedPixels // Absolute mode data is aligned to two-byte word-boundary. int padding = bytesToRead & 1; - this.stream.Skip(padding); + stream.Skip(padding); break; } @@ -554,14 +553,14 @@ private void UncompressRle4(int w, Span buffer, Span undefinedPixels /// Buffer for uncompressed data. /// Keeps track of skipped and therefore undefined pixels. /// Keeps track of rows, which have undefined pixels. - private void UncompressRle8(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels) + private void UncompressRle8(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels, BufferedReadStream stream) { Span cmd = stackalloc byte[2]; int count = 0; while (count < buffer.Length) { - if (this.stream.Read(cmd, 0, cmd.Length) != 2) + if (stream.Read(cmd, 0, cmd.Length) != 2) { BmpThrowHelper.ThrowInvalidImageContentException("Failed to read 2 bytes from stream while uncompressing RLE8 bitmap."); } @@ -582,8 +581,8 @@ private void UncompressRle8(int w, Span buffer, Span undefinedPixels break; case RleDelta: - int dx = this.stream.ReadByte(); - int dy = this.stream.ReadByte(); + int dx = stream.ReadByte(); + int dy = stream.ReadByte(); count += RleSkipDelta(count, w, dx, dy, undefinedPixels, rowsWithUndefinedPixels); break; @@ -595,7 +594,7 @@ private void UncompressRle8(int w, Span buffer, Span undefinedPixels byte[] run = new byte[length]; - this.stream.Read(run, 0, run.Length); + stream.Read(run, 0, run.Length); run.AsSpan().CopyTo(buffer[count..]); @@ -604,7 +603,7 @@ private void UncompressRle8(int w, Span buffer, Span undefinedPixels // Absolute mode data is aligned to two-byte word-boundary. int padding = length & 1; - this.stream.Skip(padding); + stream.Skip(padding); break; } @@ -633,14 +632,14 @@ private void UncompressRle8(int w, Span buffer, Span undefinedPixels /// Buffer for uncompressed data. /// Keeps track of skipped and therefore undefined pixels. /// Keeps track of rows, which have undefined pixels. - private void UncompressRle24(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels) + private void UncompressRle24(int w, Span buffer, Span undefinedPixels, Span rowsWithUndefinedPixels, BufferedReadStream stream) { Span cmd = stackalloc byte[2]; int uncompressedPixels = 0; while (uncompressedPixels < buffer.Length) { - if (this.stream.Read(cmd, 0, cmd.Length) != 2) + if (stream.Read(cmd, 0, cmd.Length) != 2) { BmpThrowHelper.ThrowInvalidImageContentException("Failed to read 2 bytes from stream while uncompressing RLE24 bitmap."); } @@ -661,8 +660,8 @@ private void UncompressRle24(int w, Span buffer, Span undefinedPixel break; case RleDelta: - int dx = this.stream.ReadByte(); - int dy = this.stream.ReadByte(); + int dx = stream.ReadByte(); + int dy = stream.ReadByte(); uncompressedPixels += RleSkipDelta(uncompressedPixels, w, dx, dy, undefinedPixels, rowsWithUndefinedPixels); break; @@ -674,7 +673,7 @@ private void UncompressRle24(int w, Span buffer, Span undefinedPixel byte[] run = new byte[length * 3]; - this.stream.Read(run, 0, run.Length); + stream.Read(run, 0, run.Length); run.AsSpan().CopyTo(buffer[(uncompressedPixels * 3)..]); @@ -683,7 +682,7 @@ private void UncompressRle24(int w, Span buffer, Span undefinedPixel // Absolute mode data is aligned to two-byte word-boundary. int padding = run.Length & 1; - this.stream.Skip(padding); + stream.Skip(padding); break; } @@ -692,8 +691,8 @@ private void UncompressRle24(int w, Span buffer, Span undefinedPixel { int max = uncompressedPixels + cmd[0]; byte blueIdx = cmd[1]; - byte greenIdx = (byte)this.stream.ReadByte(); - byte redIdx = (byte)this.stream.ReadByte(); + byte greenIdx = (byte)stream.ReadByte(); + byte redIdx = (byte)stream.ReadByte(); int bufferIdx = uncompressedPixels * 3; for (; uncompressedPixels < max; uncompressedPixels++) @@ -807,7 +806,7 @@ private static int RleSkipDelta( /// Usually 4 bytes, but in case of Windows 2.x bitmaps or OS/2 1.x bitmaps /// the bytes per color palette entry's can be 3 bytes instead of 4. /// Whether the bitmap is inverted. - private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int width, int height, int bitsPerPixel, int bytesPerColorMapEntry, bool inverted) + private void ReadRgbPalette( BufferedReadStream stream, Buffer2D pixels, byte[] colors, int width, int height, int bitsPerPixel, int bytesPerColorMapEntry, bool inverted) where TPixel : unmanaged, IPixel { // Pixels per byte (bits per pixel). @@ -832,7 +831,7 @@ private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int for (int y = 0; y < height; y++) { int newY = Invert(y, height, inverted); - if (this.stream.Read(rowSpan) == 0) + if (stream.Read(rowSpan) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for a pixel row!"); } @@ -867,7 +866,7 @@ private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int /// The bitmask for the red channel. /// The bitmask for the green channel. /// The bitmask for the blue channel. - private void ReadRgb16(Buffer2D pixels, int width, int height, bool inverted, int redMask = DefaultRgb16RMask, int greenMask = DefaultRgb16GMask, int blueMask = DefaultRgb16BMask) + private void ReadRgb16(BufferedReadStream stream, Buffer2D pixels, int width, int height, bool inverted, int redMask = DefaultRgb16RMask, int greenMask = DefaultRgb16GMask, int blueMask = DefaultRgb16BMask) where TPixel : unmanaged, IPixel { int padding = CalculatePadding(width, 2); @@ -888,7 +887,7 @@ private void ReadRgb16(Buffer2D pixels, int width, int height, b for (int y = 0; y < height; y++) { - if (this.stream.Read(bufferSpan) == 0) + if (stream.Read(bufferSpan) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for a pixel row!"); } @@ -938,7 +937,7 @@ private void ReadRgb16(Buffer2D pixels, int width, int height, b /// The width of the bitmap. /// The height of the bitmap. /// Whether the bitmap is inverted. - private void ReadRgb24(Buffer2D pixels, int width, int height, bool inverted) + private void ReadRgb24(BufferedReadStream stream, Buffer2D pixels, int width, int height, bool inverted) where TPixel : unmanaged, IPixel { int padding = CalculatePadding(width, 3); @@ -947,7 +946,7 @@ private void ReadRgb24(Buffer2D pixels, int width, int height, b for (int y = 0; y < height; y++) { - if (this.stream.Read(rowSpan) == 0) + if (stream.Read(rowSpan) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for a pixel row!"); } @@ -970,7 +969,7 @@ private void ReadRgb24(Buffer2D pixels, int width, int height, b /// The width of the bitmap. /// The height of the bitmap. /// Whether the bitmap is inverted. - private void ReadRgb32Fast(Buffer2D pixels, int width, int height, bool inverted) + private void ReadRgb32Fast(BufferedReadStream stream, Buffer2D pixels, int width, int height, bool inverted) where TPixel : unmanaged, IPixel { int padding = CalculatePadding(width, 4); @@ -979,7 +978,7 @@ private void ReadRgb32Fast(Buffer2D pixels, int width, int heigh for (int y = 0; y < height; y++) { - if (this.stream.Read(rowSpan) == 0) + if (stream.Read(rowSpan) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for a pixel row!"); } @@ -1003,7 +1002,7 @@ private void ReadRgb32Fast(Buffer2D pixels, int width, int heigh /// The width of the bitmap. /// The height of the bitmap. /// Whether the bitmap is inverted. - private void ReadRgb32Slow(Buffer2D pixels, int width, int height, bool inverted) + private void ReadRgb32Slow(BufferedReadStream stream, Buffer2D pixels, int width, int height, bool inverted) where TPixel : unmanaged, IPixel { int padding = CalculatePadding(width, 4); @@ -1011,7 +1010,7 @@ private void ReadRgb32Slow(Buffer2D pixels, int width, int heigh using IMemoryOwner bgraRow = this.memoryAllocator.Allocate(width); Span rowSpan = row.GetSpan(); Span bgraRowSpan = bgraRow.GetSpan(); - long currentPosition = this.stream.Position; + long currentPosition = stream.Position; bool hasAlpha = false; // Loop though the rows checking each pixel. We start by assuming it's @@ -1019,7 +1018,7 @@ private void ReadRgb32Slow(Buffer2D pixels, int width, int heigh // actually a BGRA image, and change tactics accordingly. for (int y = 0; y < height; y++) { - if (this.stream.Read(rowSpan) == 0) + if (stream.Read(rowSpan) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for a pixel row!"); } @@ -1048,14 +1047,14 @@ private void ReadRgb32Slow(Buffer2D pixels, int width, int heigh } // Reset our stream for a second pass. - this.stream.Position = currentPosition; + stream.Position = currentPosition; // Process the pixels in bulk taking the raw alpha component value. if (hasAlpha) { for (int y = 0; y < height; y++) { - if (this.stream.Read(rowSpan) == 0) + if (stream.Read(rowSpan) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for a pixel row!"); } @@ -1076,7 +1075,7 @@ private void ReadRgb32Slow(Buffer2D pixels, int width, int heigh // Slow path. We need to set each alpha component value to fully opaque. for (int y = 0; y < height; y++) { - if (this.stream.Read(rowSpan) == 0) + if (stream.Read(rowSpan) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for a pixel row!"); } @@ -1112,7 +1111,7 @@ private void ReadRgb32Slow(Buffer2D pixels, int width, int heigh /// The bitmask for the green channel. /// The bitmask for the blue channel. /// The bitmask for the alpha channel. - private void ReadRgb32BitFields(Buffer2D pixels, int width, int height, bool inverted, int redMask, int greenMask, int blueMask, int alphaMask) + private void ReadRgb32BitFields(BufferedReadStream stream, Buffer2D pixels, int width, int height, bool inverted, int redMask, int greenMask, int blueMask, int alphaMask) where TPixel : unmanaged, IPixel { TPixel color = default; @@ -1141,7 +1140,7 @@ private void ReadRgb32BitFields(Buffer2D pixels, int width, int for (int y = 0; y < height; y++) { - if (this.stream.Read(bufferSpan) == 0) + if (stream.Read(bufferSpan) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for a pixel row!"); } @@ -1227,10 +1226,12 @@ private static int CountBits(uint n) /// /// Reads the from the stream. /// - private void ReadInfoHeader() + [MemberNotNull(nameof(metadata))] + [MemberNotNull(nameof(bmpMetadata))] + private void ReadInfoHeader(BufferedReadStream stream) { Span buffer = stackalloc byte[BmpInfoHeader.MaxHeaderSize]; - long infoHeaderStart = this.stream.Position; + long infoHeaderStart = stream.Position; // Resolution is stored in PPM. this.metadata = new ImageMetadata @@ -1239,7 +1240,7 @@ private void ReadInfoHeader() }; // Read the header size. - this.stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize); + stream.Read(buffer, 0, BmpInfoHeader.HeaderSizeSize); int headerSize = BinaryPrimitives.ReadInt32LittleEndian(buffer); if (headerSize is < BmpInfoHeader.CoreSize or > BmpInfoHeader.MaxHeaderSize) @@ -1248,7 +1249,7 @@ private void ReadInfoHeader() } // Read the rest of the header. - this.stream.Read(buffer, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize); + stream.Read(buffer, BmpInfoHeader.HeaderSizeSize, headerSize - BmpInfoHeader.HeaderSizeSize); BmpInfoHeaderType infoHeaderType = BmpInfoHeaderType.WinVersion2; if (headerSize == BmpInfoHeader.CoreSize) @@ -1274,7 +1275,7 @@ private void ReadInfoHeader() if (this.infoHeader.Compression == BmpCompression.BitFields) { byte[] bitfieldsBuffer = new byte[12]; - this.stream.Read(bitfieldsBuffer, 0, 12); + stream.Read(bitfieldsBuffer, 0, 12); Span data = bitfieldsBuffer.AsSpan(); this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data[..4]); this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); @@ -1283,7 +1284,7 @@ private void ReadInfoHeader() else if (this.infoHeader.Compression == BmpCompression.BI_ALPHABITFIELDS) { byte[] bitfieldsBuffer = new byte[16]; - this.stream.Read(bitfieldsBuffer, 0, 16); + stream.Read(bitfieldsBuffer, 0, 16); Span data = bitfieldsBuffer.AsSpan(); this.infoHeader.RedMask = BinaryPrimitives.ReadInt32LittleEndian(data[..4]); this.infoHeader.GreenMask = BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)); @@ -1323,12 +1324,12 @@ private void ReadInfoHeader() if (this.infoHeader.ProfileData != 0 && this.infoHeader.ProfileSize != 0) { // Read color profile. - long streamPosition = this.stream.Position; + long streamPosition = stream.Position; byte[] iccProfileData = new byte[this.infoHeader.ProfileSize]; - this.stream.Position = infoHeaderStart + this.infoHeader.ProfileData; - this.stream.Read(iccProfileData); + stream.Position = infoHeaderStart + this.infoHeader.ProfileData; + stream.Read(iccProfileData); this.metadata.IccProfile = new IccProfile(iccProfileData); - this.stream.Position = streamPosition; + stream.Position = streamPosition; } } else @@ -1357,10 +1358,10 @@ private void ReadInfoHeader() /// /// Reads the from the stream. /// - private void ReadFileHeader() + private void ReadFileHeader(BufferedReadStream stream) { Span buffer = stackalloc byte[BmpFileHeader.Size]; - this.stream.Read(buffer, 0, BmpFileHeader.Size); + stream.Read(buffer, 0, BmpFileHeader.Size); short fileTypeMarker = BinaryPrimitives.ReadInt16LittleEndian(buffer); switch (fileTypeMarker) @@ -1374,7 +1375,7 @@ private void ReadFileHeader() // Because we only decode the first bitmap in the array, the array header will be ignored. // The bitmap file header of the first image follows the array header. - this.stream.Read(buffer, 0, BmpFileHeader.Size); + stream.Read(buffer, 0, BmpFileHeader.Size); this.fileHeader = BmpFileHeader.Parse(buffer); if (this.fileHeader.Type != BmpConstants.TypeMarkers.Bitmap) { @@ -1397,12 +1398,12 @@ private void ReadFileHeader() /// The color palette. /// Bytes per color palette entry. Usually 4 bytes, but in case of Windows 2.x bitmaps or OS/2 1.x bitmaps /// the bytes per color palette entry's can be 3 bytes instead of 4. + [MemberNotNull(nameof(metadata))] + [MemberNotNull(nameof(bmpMetadata))] private int ReadImageHeaders(BufferedReadStream stream, out bool inverted, out byte[] palette) { - this.stream = stream; - - this.ReadFileHeader(); - this.ReadInfoHeader(); + this.ReadFileHeader(stream); + this.ReadInfoHeader(stream); // see http://www.drdobbs.com/architecture-and-design/the-bmp-file-format-part-1/184409517 // If the height is negative, then this is a Windows bitmap whose origin @@ -1450,13 +1451,13 @@ private int ReadImageHeaders(BufferedReadStream stream, out bool inverted, out b colorMapSizeBytes = this.infoHeader.ClrUsed * bytesPerColorMapEntry; } - palette = null; + palette = Array.Empty(); if (colorMapSizeBytes > 0) { // Usually the color palette is 1024 byte (256 colors * 4), but the documentation does not mention a size limit. // Make sure, that we will not read pass the bitmap offset (starting position of image data). - if ((this.stream.Position + colorMapSizeBytes) > this.fileHeader.Offset) + if ((stream.Position + colorMapSizeBytes) > this.fileHeader.Offset) { BmpThrowHelper.ThrowInvalidImageContentException( $"Reading the color map would read beyond the bitmap offset. Either the color map size of '{colorMapSizeBytes}' is invalid or the bitmap offset."); @@ -1464,21 +1465,21 @@ private int ReadImageHeaders(BufferedReadStream stream, out bool inverted, out b palette = new byte[colorMapSizeBytes]; - if (this.stream.Read(palette, 0, colorMapSizeBytes) == 0) + if (stream.Read(palette, 0, colorMapSizeBytes) == 0) { BmpThrowHelper.ThrowInvalidImageContentException("Could not read enough data for the palette!"); } } - int skipAmount = this.fileHeader.Offset - (int)this.stream.Position; - if ((skipAmount + (int)this.stream.Position) > this.stream.Length) + int skipAmount = this.fileHeader.Offset - (int)stream.Position; + if ((skipAmount + (int)stream.Position) > stream.Length) { BmpThrowHelper.ThrowInvalidImageContentException("Invalid file header offset found. Offset is greater than the stream length."); } if (skipAmount > 0) { - this.stream.Skip(skipAmount); + stream.Skip(skipAmount); } return bytesPerColorMapEntry; diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs index a410a862b5..4b947660fd 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoder.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoder.cs @@ -29,7 +29,7 @@ public sealed class BmpEncoder : IImageEncoder, IBmpEncoderOptions /// Gets or sets the quantizer for reducing the color count for 8-Bit images. /// Defaults to Wu Quantizer. /// - public IQuantizer Quantizer { get; set; } + public IQuantizer? Quantizer { get; set; } /// public void Encode(Image image, Stream stream) diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index 471e741826..bc97b37647 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -72,7 +72,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals /// /// The global configuration. /// - private Configuration configuration; + private Configuration? configuration; /// /// The color depth, in number of bits per pixel. @@ -136,7 +136,7 @@ public void Encode(Image image, Stream stream, CancellationToken _ => 0 }; - byte[] iccProfileData = null; + byte[]? iccProfileData = null; int iccProfileSize = 0; if (metadata.IccProfile != null) { @@ -176,7 +176,7 @@ public void Encode(Image image, Stream stream, CancellationToken /// The metadata. /// The icc profile data. /// The bitmap information header. - private BmpInfoHeader CreateBmpInfoHeader(int width, int height, int infoHeaderSize, short bpp, int bytesPerLine, ImageMetadata metadata, byte[] iccProfileData) + private BmpInfoHeader CreateBmpInfoHeader(int width, int height, int infoHeaderSize, short bpp, int bytesPerLine, ImageMetadata metadata, byte[]? iccProfileData) { int hResolution = 0; int vResolution = 0; @@ -228,7 +228,7 @@ private BmpInfoHeader CreateBmpInfoHeader(int width, int height, int infoHeaderS infoHeader.Compression = BmpCompression.BitFields; } - if (this.infoHeaderType is BmpInfoHeaderType.WinVersion5 && metadata.IccProfile != null) + if (this.infoHeaderType is BmpInfoHeaderType.WinVersion5 && metadata.IccProfile != null && iccProfileData != null) { infoHeader.ProfileSize = iccProfileData.Length; infoHeader.CsType = BmpColorSpace.PROFILE_EMBEDDED; @@ -244,7 +244,7 @@ private BmpInfoHeader CreateBmpInfoHeader(int width, int height, int infoHeaderS /// The stream to write to. /// The color profile data. /// The buffer. - private static void WriteColorProfile(Stream stream, byte[] iccProfileData, Span buffer) + private static void WriteColorProfile(Stream stream, byte[]? iccProfileData, Span buffer) { if (iccProfileData != null) { @@ -314,7 +314,7 @@ private void WriteBitmapInfoHeader(Stream stream, BmpInfoHeader infoHeader, Span private void WriteImage(Stream stream, ImageFrame image) where TPixel : unmanaged, IPixel { - Buffer2D pixels = image.PixelBuffer; + Buffer2D pixels = image.PixelBuffer!; switch (this.bitsPerPixel) { case BmpBitsPerPixel.Pixel32: @@ -461,6 +461,8 @@ private void Write8BitPixelData(Stream stream, ImageFrame image) private void Write8BitColor(Stream stream, ImageFrame image, Span colorPalette) where TPixel : unmanaged, IPixel { + ArgumentNullException.ThrowIfNull(this.configuration); + using IQuantizer frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer(this.configuration); using IndexedImageFrame quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image, image.Bounds()); @@ -503,7 +505,7 @@ private void Write8BitPixelData(Stream stream, ImageFrame image, } stream.Write(colorPalette); - Buffer2D imageBuffer = image.PixelBuffer; + Buffer2D imageBuffer = image.PixelBuffer!; for (int y = image.Height - 1; y >= 0; y--) { ReadOnlySpan inputPixelRow = imageBuffer.DangerousGetRowSpan(y); @@ -526,6 +528,8 @@ private void Write8BitPixelData(Stream stream, ImageFrame image, private void Write4BitPixelData(Stream stream, ImageFrame image) where TPixel : unmanaged, IPixel { + ArgumentNullException.ThrowIfNull(this.configuration); + using IQuantizer frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer(this.configuration, new QuantizerOptions() { MaxColors = 16 @@ -570,6 +574,8 @@ private void Write4BitPixelData(Stream stream, ImageFrame image) private void Write2BitPixelData(Stream stream, ImageFrame image) where TPixel : unmanaged, IPixel { + ArgumentNullException.ThrowIfNull(this.configuration); + using IQuantizer frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer(this.configuration, new QuantizerOptions() { MaxColors = 4 @@ -623,6 +629,8 @@ private void Write2BitPixelData(Stream stream, ImageFrame image) private void Write1BitPixelData(Stream stream, ImageFrame image) where TPixel : unmanaged, IPixel { + ArgumentNullException.ThrowIfNull(this.configuration); + using IQuantizer frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer(this.configuration, new QuantizerOptions() { MaxColors = 2 diff --git a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs index a10f6b74a9..162c8ed399 100644 --- a/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Bmp/BmpImageFormatDetector.cs @@ -14,7 +14,7 @@ public sealed class BmpImageFormatDetector : IImageFormatDetector public int HeaderSize => 2; /// - public IImageFormat DetectFormat(ReadOnlySpan header) + public IImageFormat? DetectFormat(ReadOnlySpan header) { return this.IsSupportedFileFormat(header) ? BmpFormat.Instance : null; } diff --git a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs index c2ce99ec71..6a07f7867e 100644 --- a/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs +++ b/src/ImageSharp/Formats/Bmp/IBmpEncoderOptions.cs @@ -26,5 +26,5 @@ internal interface IBmpEncoderOptions /// /// Gets the quantizer for reducing the color count for 8-Bit, 4-Bit, and 1-Bit images. /// - IQuantizer Quantizer { get; } + IQuantizer? Quantizer { get; } } diff --git a/src/ImageSharp/Formats/Gif/GifDecoder.cs b/src/ImageSharp/Formats/Gif/GifDecoder.cs index cf8f4637ef..21d08e2e94 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoder.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoder.cs @@ -28,6 +28,8 @@ Image IImageDecoder.Decode(DecoderOptions options, Stream stream GifDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); + ArgumentNullException.ThrowIfNull(image); + ImageDecoderUtilities.Resize(options, image); return image; diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index ef29863d4f..1e0f98f8d2 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -23,15 +24,10 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// private readonly byte[] buffer = new byte[16]; - /// - /// The currently loaded stream. - /// - private BufferedReadStream stream; - /// /// The global color table. /// - private IMemoryOwner globalColorTable; + private IMemoryOwner? globalColorTable; /// /// The area to restore. @@ -76,12 +72,12 @@ internal sealed class GifDecoderCore : IImageDecoderInternals /// /// The abstract metadata. /// - private ImageMetadata metadata; + private ImageMetadata? metadata; /// /// The gif specific metadata. /// - private GifMetadata gifMetadata; + private GifMetadata? gifMetadata; /// /// Initializes a new instance of the class. @@ -100,15 +96,15 @@ public GifDecoderCore(DecoderOptions options) public DecoderOptions Options { get; } /// - public Size Dimensions => new(this.imageDescriptor.Width, this.imageDescriptor.Height); + public Size? Dimensions => new(this.imageDescriptor.Width, this.imageDescriptor.Height); /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { uint frameCount = 0; - Image image = null; - ImageFrame previousFrame = null; + Image? image = null; + ImageFrame? previousFrame = null; try { this.ReadLogicalScreenDescriptorAndGlobalColorTable(stream); @@ -124,23 +120,23 @@ public Image Decode(BufferedReadStream stream, CancellationToken break; } - this.ReadFrame(ref image, ref previousFrame); + this.ReadFrame(ref image, ref previousFrame, stream); } else if (nextFlag == GifConstants.ExtensionIntroducer) { switch (stream.ReadByte()) { case GifConstants.GraphicControlLabel: - this.ReadGraphicalControlExtension(); + this.ReadGraphicalControlExtension(stream); break; case GifConstants.CommentLabel: - this.ReadComments(); + this.ReadComments(stream); break; case GifConstants.ApplicationExtensionLabel: - this.ReadApplicationExtension(); + this.ReadApplicationExtension(stream); break; case GifConstants.PlainTextLabel: - this.SkipBlock(); // Not supported by any known decoder. + this.SkipBlock(stream); // Not supported by any known decoder. break; } } @@ -161,7 +157,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken this.globalColorTable?.Dispose(); } - return image; + return image!; } /// @@ -177,23 +173,23 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella { if (nextFlag == GifConstants.ImageLabel) { - this.ReadImageDescriptor(); + this.ReadImageDescriptor(stream); } else if (nextFlag == GifConstants.ExtensionIntroducer) { switch (stream.ReadByte()) { case GifConstants.GraphicControlLabel: - this.SkipBlock(); // Skip graphic control extension block + this.SkipBlock(stream); // Skip graphic control extension block break; case GifConstants.CommentLabel: - this.ReadComments(); + this.ReadComments(stream); break; case GifConstants.ApplicationExtensionLabel: - this.ReadApplicationExtension(); + this.ReadApplicationExtension(stream); break; case GifConstants.PlainTextLabel: - this.SkipBlock(); // Not supported by any known decoder. + this.SkipBlock(stream); // Not supported by any known decoder. break; } } @@ -224,9 +220,9 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella /// /// Reads the graphic control extension. /// - private void ReadGraphicalControlExtension() + private void ReadGraphicalControlExtension(BufferedReadStream stream) { - int bytesRead = this.stream.Read(this.buffer, 0, 6); + int bytesRead = stream.Read(this.buffer, 0, 6); if (bytesRead != 6) { GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the graphic control extension"); @@ -238,9 +234,9 @@ private void ReadGraphicalControlExtension() /// /// Reads the image descriptor. /// - private void ReadImageDescriptor() + private void ReadImageDescriptor(BufferedReadStream stream) { - int bytesRead = this.stream.Read(this.buffer, 0, 9); + int bytesRead = stream.Read(this.buffer, 0, 9); if (bytesRead != 9) { GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the image descriptor"); @@ -256,9 +252,9 @@ private void ReadImageDescriptor() /// /// Reads the logical screen descriptor. /// - private void ReadLogicalScreenDescriptor() + private void ReadLogicalScreenDescriptor(BufferedReadStream stream) { - int bytesRead = this.stream.Read(this.buffer, 0, 7); + int bytesRead = stream.Read(this.buffer, 0, 7); if (bytesRead != 7) { GifThrowHelper.ThrowInvalidImageContentException("Not enough data to read the logical screen descriptor"); @@ -271,22 +267,24 @@ private void ReadLogicalScreenDescriptor() /// Reads the application extension block parsing any animation or XMP information /// if present. /// - private void ReadApplicationExtension() + private void ReadApplicationExtension(BufferedReadStream stream) { - int appLength = this.stream.ReadByte(); + int appLength = stream.ReadByte(); // If the length is 11 then it's a valid extension and most likely // a NETSCAPE, XMP or ANIMEXTS extension. We want the loop count from this. if (appLength == GifConstants.ApplicationBlockSize) { - this.stream.Read(this.buffer, 0, GifConstants.ApplicationBlockSize); + stream.Read(this.buffer, 0, GifConstants.ApplicationBlockSize); bool isXmp = this.buffer.AsSpan().StartsWith(GifConstants.XmpApplicationIdentificationBytes); if (isXmp && !this.skipMetadata) { - var extension = GifXmpApplicationExtension.Read(this.stream, this.memoryAllocator); + var extension = GifXmpApplicationExtension.Read(stream, this.memoryAllocator); if (extension.Data.Length > 0) { + ArgumentNullException.ThrowIfNull(this.metadata); + this.metadata.XmpProfile = new XmpProfile(extension.Data); } @@ -294,57 +292,60 @@ private void ReadApplicationExtension() } else { - int subBlockSize = this.stream.ReadByte(); + int subBlockSize = stream.ReadByte(); // TODO: There's also a NETSCAPE buffer extension. // http://www.vurdalakov.net/misc/gif/netscape-buffering-application-extension if (subBlockSize == GifConstants.NetscapeLoopingSubBlockSize) { - this.stream.Read(this.buffer, 0, GifConstants.NetscapeLoopingSubBlockSize); + stream.Read(this.buffer, 0, GifConstants.NetscapeLoopingSubBlockSize); + + ArgumentNullException.ThrowIfNull(this.gifMetadata); + this.gifMetadata.RepeatCount = GifNetscapeLoopingApplicationExtension.Parse(this.buffer.AsSpan(1)).RepeatCount; - this.stream.Skip(1); // Skip the terminator. + stream.Skip(1); // Skip the terminator. return; } // Could be something else not supported yet. // Skip the subblock and terminator. - this.SkipBlock(subBlockSize); + this.SkipBlock(stream, subBlockSize); } return; } - this.SkipBlock(appLength); // Not supported by any known decoder. + this.SkipBlock(stream, appLength); // Not supported by any known decoder. } /// /// Skips over a block or reads its terminator. /// The length of the block to skip. /// - private void SkipBlock(int blockSize = 0) + private void SkipBlock(BufferedReadStream stream, int blockSize = 0) { if (blockSize > 0) { - this.stream.Skip(blockSize); + stream.Skip(blockSize); } int flag; - while ((flag = this.stream.ReadByte()) > 0) + while ((flag = stream.ReadByte()) > 0) { - this.stream.Skip(flag); + stream.Skip(flag); } } /// /// Reads the gif comments. /// - private void ReadComments() + private void ReadComments(BufferedReadStream stream) { int length; var stringBuilder = new StringBuilder(); - while ((length = this.stream.ReadByte()) != 0) + while ((length = stream.ReadByte()) != 0) { if (length > GifConstants.MaxCommentSubBlockLength) { @@ -353,20 +354,22 @@ private void ReadComments() if (this.skipMetadata) { - this.stream.Seek(length, SeekOrigin.Current); + stream.Seek(length, SeekOrigin.Current); continue; } using IMemoryOwner commentsBuffer = this.memoryAllocator.Allocate(length); Span commentsSpan = commentsBuffer.GetSpan(); - this.stream.Read(commentsSpan); + stream.Read(commentsSpan); string commentPart = GifConstants.Encoding.GetString(commentsSpan); stringBuilder.Append(commentPart); } if (stringBuilder.Length > 0) { + ArgumentNullException.ThrowIfNull(this.gifMetadata); + this.gifMetadata.Comments.Add(stringBuilder.ToString()); } } @@ -377,13 +380,13 @@ private void ReadComments() /// The pixel format. /// The image to decode the information to. /// The previous frame. - private void ReadFrame(ref Image image, ref ImageFrame previousFrame) + private void ReadFrame(ref Image? image, ref ImageFrame? previousFrame, BufferedReadStream stream) where TPixel : unmanaged, IPixel { - this.ReadImageDescriptor(); + this.ReadImageDescriptor(stream); - IMemoryOwner localColorTable = null; - Buffer2D indices = null; + IMemoryOwner? localColorTable = null; + Buffer2D? indices = null; try { // Determine the color table for this frame. If there is a local one, use it otherwise use the global color table. @@ -391,11 +394,11 @@ private void ReadFrame(ref Image image, ref ImageFrame p { int length = this.imageDescriptor.LocalColorTableSize * 3; localColorTable = this.configuration.MemoryAllocator.Allocate(length, AllocationOptions.Clean); - this.stream.Read(localColorTable.GetSpan()); + stream.Read(localColorTable.GetSpan()); } indices = this.configuration.MemoryAllocator.Allocate2D(this.imageDescriptor.Width, this.imageDescriptor.Height, AllocationOptions.Clean); - this.ReadFrameIndices(indices); + this.ReadFrameIndices(indices, stream); Span rawColorTable = default; if (localColorTable != null) @@ -411,7 +414,7 @@ private void ReadFrame(ref Image image, ref ImageFrame p this.ReadFrameColors(ref image, ref previousFrame, indices, colorTable, this.imageDescriptor); // Skip any remaining blocks - this.SkipBlock(); + this.SkipBlock(stream); } finally { @@ -425,10 +428,10 @@ private void ReadFrame(ref Image image, ref ImageFrame p /// /// The 2D pixel buffer to write to. [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadFrameIndices(Buffer2D indices) + private void ReadFrameIndices(Buffer2D indices, BufferedReadStream stream) { - int minCodeSize = this.stream.ReadByte(); - using var lzwDecoder = new LzwDecoder(this.configuration.MemoryAllocator, this.stream); + int minCodeSize = stream.ReadByte(); + using var lzwDecoder = new LzwDecoder(this.configuration.MemoryAllocator, stream); lzwDecoder.DecodePixels(minCodeSize, indices); } @@ -441,19 +444,21 @@ private void ReadFrameIndices(Buffer2D indices) /// The indexed pixels. /// The color table containing the available colors. /// The - private void ReadFrameColors(ref Image image, ref ImageFrame previousFrame, Buffer2D indices, ReadOnlySpan colorTable, in GifImageDescriptor descriptor) + private void ReadFrameColors(ref Image? image, ref ImageFrame? previousFrame, Buffer2D indices, ReadOnlySpan colorTable, in GifImageDescriptor descriptor) where TPixel : unmanaged, IPixel { int imageWidth = this.logicalScreenDescriptor.Width; int imageHeight = this.logicalScreenDescriptor.Height; bool transFlag = this.graphicsControlExtension.TransparencyFlag; - ImageFrame prevFrame = null; - ImageFrame currentFrame = null; + ImageFrame? prevFrame = null; + ImageFrame? currentFrame = null; ImageFrame imageFrame; if (previousFrame is null) { + ArgumentNullException.ThrowIfNull(this.metadata); + if (!transFlag) { image = new Image(this.configuration, imageWidth, imageHeight, Color.Black.ToPixel(), this.metadata); @@ -475,6 +480,8 @@ private void ReadFrameColors(ref Image image, ref ImageFrame(ref Image image, ref ImageFrame(ImageFrame frame) } var interest = Rectangle.Intersect(frame.Bounds(), this.restoreArea.Value); - Buffer2DRegion pixelRegion = frame.PixelBuffer.GetRegion(interest); + Buffer2DRegion pixelRegion = frame.PixelBuffer!.GetRegion(interest); pixelRegion.Clear(); this.restoreArea = null; @@ -631,13 +638,13 @@ private void SetFrameMetadata(ImageFrameMetadata meta) /// Reads the logical screen descriptor and global color table blocks /// /// The stream containing image data. + [MemberNotNull(nameof(metadata))] + [MemberNotNull(nameof(gifMetadata))] private void ReadLogicalScreenDescriptorAndGlobalColorTable(BufferedReadStream stream) { - this.stream = stream; - // Skip the identifier - this.stream.Skip(6); - this.ReadLogicalScreenDescriptor(); + stream.Skip(6); + this.ReadLogicalScreenDescriptor(stream); var meta = new ImageMetadata(); diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index cfd4ba36a6..ebf9b67597 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -120,7 +120,7 @@ public void Encode(Image image, Stream stream, CancellationToken this.WriteComments(gifMetadata, stream); // Write application extensions. - XmpProfile xmpProfile = image.Metadata.XmpProfile ?? image.Frames.RootFrame.Metadata.XmpProfile; + XmpProfile? xmpProfile = image.Metadata.XmpProfile ?? image.Frames.RootFrame.Metadata.XmpProfile; this.WriteApplicationExtensions(stream, image.Frames.Count, gifMetadata.RepeatCount, xmpProfile); if (useGlobalTable) @@ -174,11 +174,11 @@ private void EncodeGlobal(Image image, IndexedImageFrame paletteFrameQuantizer.Dispose(); } - private void EncodeLocal(Image image, IndexedImageFrame quantized, Stream stream) + private void EncodeLocal(Image image, IndexedImageFrame? quantized, Stream stream) where TPixel : unmanaged, IPixel { - ImageFrame previousFrame = null; - GifFrameMetadata previousMeta = null; + ImageFrame? previousFrame = null; + GifFrameMetadata? previousMeta = null; for (int i = 0; i < image.Frames.Count; i++) { ImageFrame frame = image.Frames[i]; @@ -187,7 +187,7 @@ private void EncodeLocal(Image image, IndexedImageFrame if (quantized is null) { // Allow each frame to be encoded at whatever color depth the frame designates if set. - if (previousFrame != null && previousMeta.ColorTableLength != frameMetadata.ColorTableLength + if (previousFrame != null && previousMeta?.ColorTableLength != frameMetadata.ColorTableLength && frameMetadata.ColorTableLength > 0) { QuantizerOptions options = new() @@ -324,7 +324,7 @@ private void WriteLogicalScreenDescriptor( /// The frame count fo this image. /// The animated image repeat count. /// The XMP metadata profile. Null if profile is not to be written. - private void WriteApplicationExtensions(Stream stream, int frameCount, ushort repeatCount, XmpProfile xmpProfile) + private void WriteApplicationExtensions(Stream stream, int frameCount, ushort repeatCount, XmpProfile? xmpProfile) { // Application Extension: Loop repeat count. if (frameCount > 1 && repeatCount != 1) @@ -336,7 +336,7 @@ private void WriteApplicationExtensions(Stream stream, int frameCount, ushort re // Application Extension: XMP Profile. if (xmpProfile != null) { - GifXmpApplicationExtension xmpExtension = new(xmpProfile.Data); + GifXmpApplicationExtension xmpExtension = new(xmpProfile.Data!); this.WriteExtension(xmpExtension, stream); } } @@ -425,7 +425,7 @@ private void WriteGraphicalControlExtension(GifFrameMetadata metadata, int trans private void WriteExtension(TGifExtension extension, Stream stream) where TGifExtension : struct, IGifExtension { - IMemoryOwner owner = null; + IMemoryOwner? owner = null; Span extensionBuffer; int extensionSize = extension.ContentLength; diff --git a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs index 3f657610c9..db3d429046 100644 --- a/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Gif/GifImageFormatDetector.cs @@ -12,7 +12,7 @@ public sealed class GifImageFormatDetector : IImageFormatDetector public int HeaderSize => 6; /// - public IImageFormat DetectFormat(ReadOnlySpan header) + public IImageFormat? DetectFormat(ReadOnlySpan header) { return this.IsSupportedFileFormat(header) ? GifFormat.Instance : null; } diff --git a/src/ImageSharp/Formats/IImageDecoderInternals.cs b/src/ImageSharp/Formats/IImageDecoderInternals.cs index d8cb1c6627..3f9e63992f 100644 --- a/src/ImageSharp/Formats/IImageDecoderInternals.cs +++ b/src/ImageSharp/Formats/IImageDecoderInternals.cs @@ -19,7 +19,7 @@ internal interface IImageDecoderInternals /// /// Gets the dimensions of the image being decoded. /// - Size Dimensions { get; } + Size? Dimensions { get; } /// /// Decodes the image from the specified stream. diff --git a/src/ImageSharp/Formats/IImageFormatDetector.cs b/src/ImageSharp/Formats/IImageFormatDetector.cs index 17f565d2b2..e1bdc41f8f 100644 --- a/src/ImageSharp/Formats/IImageFormatDetector.cs +++ b/src/ImageSharp/Formats/IImageFormatDetector.cs @@ -19,5 +19,5 @@ public interface IImageFormatDetector /// /// The containing the file header. /// returns the mime type of detected otherwise returns null - IImageFormat DetectFormat(ReadOnlySpan header); + IImageFormat? DetectFormat(ReadOnlySpan header); } diff --git a/src/ImageSharp/Formats/ImageDecoderUtilities.cs b/src/ImageSharp/Formats/ImageDecoderUtilities.cs index 42f15cf976..4b352a078d 100644 --- a/src/ImageSharp/Formats/ImageDecoderUtilities.cs +++ b/src/ImageSharp/Formats/ImageDecoderUtilities.cs @@ -25,7 +25,7 @@ public static void Resize(DecoderOptions options, Image image) { ResizeOptions resizeOptions = new() { - Size = options.TargetSize.Value, + Size = options.TargetSize!.Value, Sampler = options.Sampler, Mode = ResizeMode.Max }; @@ -66,7 +66,7 @@ internal static IImageInfo Identify( } catch (InvalidMemoryOperationException ex) { - throw new InvalidImageContentException(decoder.Dimensions, ex); + throw new InvalidImageContentException(decoder.Dimensions!.Value, ex); } } @@ -94,7 +94,7 @@ internal static Image Decode( } catch (InvalidMemoryOperationException ex) { - throw largeImageExceptionFactory(ex, decoder.Dimensions); + throw largeImageExceptionFactory(ex, decoder.Dimensions!.Value); } } diff --git a/src/ImageSharp/Formats/ImageFormatManager.cs b/src/ImageSharp/Formats/ImageFormatManager.cs index 9f22c62294..640bff30f2 100644 --- a/src/ImageSharp/Formats/ImageFormatManager.cs +++ b/src/ImageSharp/Formats/ImageFormatManager.cs @@ -92,7 +92,7 @@ public void AddImageFormat(IImageFormat format) /// /// The extension to discover /// The if found otherwise null - public IImageFormat FindFormatByFileExtension(string extension) + public IImageFormat? FindFormatByFileExtension(string extension) { Guard.NotNullOrWhiteSpace(extension, nameof(extension)); @@ -109,7 +109,7 @@ public IImageFormat FindFormatByFileExtension(string extension) /// /// The mime-type to discover /// The if found; otherwise null - public IImageFormat FindFormatByMimeType(string mimeType) + public IImageFormat? FindFormatByMimeType(string mimeType) => this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase)); /// @@ -159,11 +159,11 @@ public void AddImageFormatDetector(IImageFormatDetector detector) /// /// The format to discover /// The if found otherwise null - public IImageDecoder FindDecoder(IImageFormat format) + public IImageDecoder? FindDecoder(IImageFormat format) { Guard.NotNull(format, nameof(format)); - return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder) + return this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder? decoder) ? decoder : null; } @@ -173,11 +173,11 @@ public IImageDecoder FindDecoder(IImageFormat format) /// /// The format to discover /// The if found otherwise null - public IImageEncoder FindEncoder(IImageFormat format) + public IImageEncoder? FindEncoder(IImageFormat format) { Guard.NotNull(format, nameof(format)); - return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder) + return this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder? encoder) ? encoder : null; } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 3023a01c9c..e25ddf42c9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -470,7 +470,7 @@ public bool Equals(Block8x8F other) && this.V7R == other.V7R; /// - public override bool Equals(object obj) => this.Equals((Block8x8F)obj); + public override bool Equals(object? obj) => obj is not null && this.Equals((Block8x8F)obj); /// public override int GetHashCode() diff --git a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs index f0aa2c321d..639a36aedd 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/ColorConverters/JpegColorConverterBase.cs @@ -71,7 +71,7 @@ protected JpegColorConverterBase(JpegColorSpace colorSpace, int precision) /// Invalid colorspace. public static JpegColorConverterBase GetConverter(JpegColorSpace colorSpace, int precision) { - JpegColorConverterBase converter = Array.Find( + JpegColorConverterBase? converter = Array.Find( Converters, c => c.ColorSpace == colorSpace && c.Precision == precision); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs index b3463b5169..c9ee55cd77 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs @@ -89,7 +89,7 @@ public bool Equals(AdobeMarker other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is AdobeMarker other && this.Equals(other); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticDecodingComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticDecodingComponent.cs index 869b9ae01b..76812a3baa 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticDecodingComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticDecodingComponent.cs @@ -20,10 +20,10 @@ public ArithmeticDecodingComponent(MemoryAllocator memoryAllocator, JpegFrame fr /// /// Gets or sets the dc statistics. /// - public ArithmeticStatistics DcStatistics { get; set; } + public ArithmeticStatistics? DcStatistics { get; set; } /// /// Gets or sets the ac statistics. /// - public ArithmeticStatistics AcStatistics { get; set; } + public ArithmeticStatistics? AcStatistics { get; set; } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs index a62efa8125..182b96b1db 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ArithmeticScanDecoder.cs @@ -22,12 +22,12 @@ internal class ArithmeticScanDecoder : IJpegScanDecoder /// /// instance containing decoding-related information. /// - private JpegFrame frame; + private JpegFrame? frame; /// /// Shortcut for .Components. /// - private IJpegComponent[] components; + private IJpegComponent[]? components; /// /// Number of component in the current scan. @@ -44,13 +44,13 @@ internal class ArithmeticScanDecoder : IJpegScanDecoder /// private int todo; - private readonly SpectralConverter spectralConverter; + private readonly SpectralConverter? spectralConverter; private JpegBitReader scanBuffer; - private ArithmeticDecodingTable[] dcDecodingTables; + private ArithmeticDecodingTable?[]? dcDecodingTables; - private ArithmeticDecodingTable[] acDecodingTables; + private ArithmeticDecodingTable?[]? acDecodingTables; private readonly byte[] fixedBin = { 113, 0, 0, 0 }; @@ -185,7 +185,7 @@ internal class ArithmeticScanDecoder : IJpegScanDecoder /// The input stream. /// Spectral to pixel converter. /// The token to monitor cancellation. - public ArithmeticScanDecoder(BufferedReadStream stream, SpectralConverter converter, CancellationToken cancellationToken) + public ArithmeticScanDecoder(BufferedReadStream stream, SpectralConverter? converter, CancellationToken cancellationToken) { this.stream = stream; this.spectralConverter = converter; @@ -220,9 +220,14 @@ public int ResetInterval public void InitDecodingTables(List arithmeticDecodingTables) { - for (int i = 0; i < this.components.Length; i++) + for (int i = 0; i < this.components?.Length; i++) { - ArithmeticDecodingComponent component = this.components[i] as ArithmeticDecodingComponent; + ArithmeticDecodingComponent? component = this.components[i] as ArithmeticDecodingComponent; + + ArgumentNullException.ThrowIfNull(component); + ArgumentNullException.ThrowIfNull(this.dcDecodingTables); + ArgumentNullException.ThrowIfNull(this.acDecodingTables); + this.dcDecodingTables[i] = GetArithmeticTable(arithmeticDecodingTables, true, component.DcTableId); component.DcStatistics = this.CreateOrGetStatisticsBin(true, component.DcTableId); this.acDecodingTables[i] = GetArithmeticTable(arithmeticDecodingTables, false, component.AcTableId); @@ -244,6 +249,7 @@ public void ParseEntropyCodedData(int scanComponentCount) this.scanBuffer = new JpegBitReader(this.stream); + ArgumentNullException.ThrowIfNull(this.frame); this.frame.AllocateComponents(); if (this.frame.Progressive) @@ -267,13 +273,15 @@ public void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) this.frame = frame; this.components = frame.Components; + ArgumentNullException.ThrowIfNull(this.components); + this.dcDecodingTables = new ArithmeticDecodingTable[this.components.Length]; this.acDecodingTables = new ArithmeticDecodingTable[this.components.Length]; - this.spectralConverter.InjectFrameData(frame, jpegData); + this.spectralConverter?.InjectFrameData(frame, jpegData); } - private static ArithmeticDecodingTable GetArithmeticTable(List arithmeticDecodingTables, bool isDcTable, int identifier) + private static ArithmeticDecodingTable? GetArithmeticTable(List arithmeticDecodingTables, bool isDcTable, int identifier) { int tableClass = isDcTable ? 0 : 1; @@ -310,7 +318,7 @@ private ArithmeticStatistics CreateOrGetStatisticsBin(bool dc, int identifier, b private void ParseBaselineData() { - for (int i = 0; i < this.components.Length; i++) + for (int i = 0; i < this.components?.Length; i++) { ArithmeticDecodingComponent component = (ArithmeticDecodingComponent)this.components[i]; component.DcPredictor = 0; @@ -323,15 +331,19 @@ private void ParseBaselineData() if (this.scanComponentCount != 1) { - this.spectralConverter.PrepareForDecoding(); + this.spectralConverter?.PrepareForDecoding(); this.ParseBaselineDataInterleaved(); - this.spectralConverter.CommitConversion(); + this.spectralConverter?.CommitConversion(); + } + else if (this.frame is null) + { + ArgumentNullException.ThrowIfNull(this.frame); } else if (this.frame.ComponentCount == 1) { - this.spectralConverter.PrepareForDecoding(); + this.spectralConverter?.PrepareForDecoding(); this.ParseBaselineDataSingleComponent(); - this.spectralConverter.CommitConversion(); + this.spectralConverter?.CommitConversion(); } else { @@ -343,7 +355,7 @@ private void ParseProgressiveData() { this.CheckProgressiveData(); - foreach (ArithmeticDecodingComponent component in this.components) + foreach (ArithmeticDecodingComponent component in this.components!) { if (this.SpectralStart == 0 && this.SuccessiveHigh == 0) { @@ -423,6 +435,7 @@ private void CheckProgressiveData() private void ParseBaselineDataInterleaved() { int mcu = 0; + ArgumentNullException.ThrowIfNull(this.frame); int mcusPerColumn = this.frame.McusPerColumn; int mcusPerLine = this.frame.McusPerLine; ref JpegBitReader reader = ref this.scanBuffer; @@ -438,11 +451,16 @@ private void ParseBaselineDataInterleaved() int mcuCol = mcu % mcusPerLine; for (int k = 0; k < this.scanComponentCount; k++) { + ArgumentNullException.ThrowIfNull(this.frame.ComponentOrder); int order = this.frame.ComponentOrder[k]; - ArithmeticDecodingComponent component = this.components[order] as ArithmeticDecodingComponent; + ArithmeticDecodingComponent? component = this.components?[order] as ArithmeticDecodingComponent; + + ArgumentNullException.ThrowIfNull(component); + ArgumentNullException.ThrowIfNull(this.dcDecodingTables); + ArgumentNullException.ThrowIfNull(this.acDecodingTables); - ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; - ref ArithmeticDecodingTable acDecodingTable = ref this.acDecodingTables[component.AcTableId]; + ref ArithmeticDecodingTable? dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; + ref ArithmeticDecodingTable? acDecodingTable = ref this.acDecodingTables[component.AcTableId]; int h = component.HorizontalSamplingFactor; int v = component.VerticalSamplingFactor; @@ -452,7 +470,7 @@ private void ParseBaselineDataInterleaved() int mcuColMulh = mcuCol * h; for (int y = 0; y < v; y++) { - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(y); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(y); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int x = 0; x < h; x++) @@ -461,7 +479,7 @@ private void ParseBaselineDataInterleaved() { // It is very likely that some spectral data was decoded before we've encountered 'end of scan' // so we need to decode what's left and return (or maybe throw?) - this.spectralConverter.ConvertStrideBaseline(); + this.spectralConverter?.ConvertStrideBaseline(); return; } @@ -483,18 +501,24 @@ ref Unsafe.Add(ref blockRef, (nint)(uint)blockCol), } // Convert from spectral to actual pixels via given converter. - this.spectralConverter.ConvertStrideBaseline(); + this.spectralConverter?.ConvertStrideBaseline(); } } private void ParseBaselineDataSingleComponent() { - ArithmeticDecodingComponent component = this.frame.Components[0] as ArithmeticDecodingComponent; + ArgumentNullException.ThrowIfNull(this.frame); + ArithmeticDecodingComponent? component = this.frame.Components?[0] as ArithmeticDecodingComponent; + + ArgumentNullException.ThrowIfNull(component); + ArgumentNullException.ThrowIfNull(this.dcDecodingTables); + ArgumentNullException.ThrowIfNull(this.acDecodingTables); + int mcuLines = this.frame.McusPerColumn; int w = component.WidthInBlocks; int h = component.SamplingFactors.Height; - ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; - ref ArithmeticDecodingTable acDecodingTable = ref this.acDecodingTables[component.AcTableId]; + ref ArithmeticDecodingTable? dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; + ref ArithmeticDecodingTable? acDecodingTable = ref this.acDecodingTables[component.AcTableId]; ref JpegBitReader reader = ref this.scanBuffer; @@ -505,7 +529,7 @@ private void ParseBaselineDataSingleComponent() // Decode from binary to spectral. for (int j = 0; j < h; j++) { - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(j); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int k = 0; k < w; k++) @@ -514,7 +538,7 @@ private void ParseBaselineDataSingleComponent() { // It is very likely that some spectral data was decoded before we've encountered 'end of scan' // so we need to decode what's left and return (or maybe throw?) - this.spectralConverter.ConvertStrideBaseline(); + this.spectralConverter?.ConvertStrideBaseline(); return; } @@ -529,25 +553,31 @@ ref Unsafe.Add(ref blockRef, (nint)(uint)k), } // Convert from spectral to actual pixels via given converter. - this.spectralConverter.ConvertStrideBaseline(); + this.spectralConverter?.ConvertStrideBaseline(); } } private void ParseBaselineDataNonInterleaved() { - ArithmeticDecodingComponent component = (ArithmeticDecodingComponent)this.components[this.frame.ComponentOrder[0]]; + ArgumentNullException.ThrowIfNull(this.frame); + ArgumentNullException.ThrowIfNull(this.frame.ComponentOrder); + ArithmeticDecodingComponent? component = (ArithmeticDecodingComponent?)this.components?[this.frame.ComponentOrder[0]]; ref JpegBitReader reader = ref this.scanBuffer; + ArgumentNullException.ThrowIfNull(component); + ArgumentNullException.ThrowIfNull(this.dcDecodingTables); + ArgumentNullException.ThrowIfNull(this.acDecodingTables); + int w = component.WidthInBlocks; int h = component.HeightInBlocks; - ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; - ref ArithmeticDecodingTable acDecodingTable = ref this.acDecodingTables[component.AcTableId]; + ref ArithmeticDecodingTable? dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; + ref ArithmeticDecodingTable? acDecodingTable = ref this.acDecodingTables[component.AcTableId]; for (int j = 0; j < h; j++) { this.cancellationToken.ThrowIfCancellationRequested(); - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(j); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int i = 0; i < w; i++) @@ -571,6 +601,7 @@ ref Unsafe.Add(ref blockRef, (nint)(uint)i), private void ParseProgressiveDataInterleaved() { int mcu = 0; + ArgumentNullException.ThrowIfNull(this.frame); int mcusPerColumn = this.frame.McusPerColumn; int mcusPerLine = this.frame.McusPerLine; ref JpegBitReader reader = ref this.scanBuffer; @@ -583,9 +614,14 @@ private void ParseProgressiveDataInterleaved() int mcuRow = Math.DivRem(mcu, mcusPerLine, out int mcuCol); for (int k = 0; k < this.scanComponentCount; k++) { + ArgumentNullException.ThrowIfNull(this.frame.ComponentOrder); int order = this.frame.ComponentOrder[k]; - ArithmeticDecodingComponent component = this.components[order] as ArithmeticDecodingComponent; - ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; + ArithmeticDecodingComponent? component = this.components?[order] as ArithmeticDecodingComponent; + + ArgumentNullException.ThrowIfNull(component); + ArgumentNullException.ThrowIfNull(this.dcDecodingTables); + + ref ArithmeticDecodingTable? dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; int h = component.HorizontalSamplingFactor; int v = component.VerticalSamplingFactor; @@ -596,7 +632,7 @@ private void ParseProgressiveDataInterleaved() for (int y = 0; y < v; y++) { int blockRow = (mcuRow * v) + y; - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(blockRow); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(blockRow); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int x = 0; x < h; x++) @@ -626,21 +662,26 @@ ref Unsafe.Add(ref blockRef, (nint)(uint)blockCol), private void ParseProgressiveDataNonInterleaved() { - ArithmeticDecodingComponent component = this.components[this.frame.ComponentOrder[0]] as ArithmeticDecodingComponent; + ArgumentNullException.ThrowIfNull(this.frame); + ArgumentNullException.ThrowIfNull(this.frame.ComponentOrder); + ArithmeticDecodingComponent? component = this.components?[this.frame.ComponentOrder[0]] as ArithmeticDecodingComponent; ref JpegBitReader reader = ref this.scanBuffer; + ArgumentNullException.ThrowIfNull(component); + int w = component.WidthInBlocks; int h = component.HeightInBlocks; if (this.SpectralStart == 0) { - ref ArithmeticDecodingTable dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; + ArgumentNullException.ThrowIfNull(this.dcDecodingTables); + ref ArithmeticDecodingTable? dcDecodingTable = ref this.dcDecodingTables[component.DcTableId]; for (int j = 0; j < h; j++) { this.cancellationToken.ThrowIfCancellationRequested(); - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(j); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int i = 0; i < w; i++) @@ -661,13 +702,14 @@ ref Unsafe.Add(ref blockRef, (nint)(uint)i), } else { - ref ArithmeticDecodingTable acDecodingTable = ref this.acDecodingTables[component.AcTableId]; + ArgumentNullException.ThrowIfNull(this.acDecodingTables); + ref ArithmeticDecodingTable? acDecodingTable = ref this.acDecodingTables[component.AcTableId]; for (int j = 0; j < h; j++) { this.cancellationToken.ThrowIfCancellationRequested(); - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(j); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int i = 0; i < w; i++) @@ -688,7 +730,7 @@ ref Unsafe.Add(ref blockRef, (nint)(uint)i), } } - private void DecodeBlockProgressiveDc(ArithmeticDecodingComponent component, ref Block8x8 block, ref ArithmeticDecodingTable dcTable) + private void DecodeBlockProgressiveDc(ArithmeticDecodingComponent component, ref Block8x8 block, ref ArithmeticDecodingTable? dcTable) { if (dcTable == null) { @@ -704,7 +746,7 @@ private void DecodeBlockProgressiveDc(ArithmeticDecodingComponent component, ref // Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients. // Table F.4: Point to statistics bin S0 for DC coefficient coding. - ref byte st = ref Unsafe.Add(ref component.DcStatistics.GetReference(), component.DcContext); + ref byte st = ref Unsafe.Add(ref component.DcStatistics!.GetReference(), component.DcContext); // Figure F.19: Decode_DC_DIFF if (this.DecodeBinaryDecision(ref reader, ref st) == 0) @@ -735,7 +777,7 @@ private void DecodeBlockProgressiveDc(ArithmeticDecodingComponent component, ref } // Section F.1.4.4.1.2: Establish dc_context conditioning category. - if (m < (int)((1L << dcTable.DcL) >> 1)) + if (m < (int)((1L << dcTable!.DcL) >> 1)) { component.DcContext = 0; // Zero diff category. } @@ -780,12 +822,12 @@ private void DecodeBlockProgressiveDc(ArithmeticDecodingComponent component, ref } } - private void DecodeBlockProgressiveAc(ArithmeticDecodingComponent component, ref Block8x8 block, ref ArithmeticDecodingTable acTable) + private void DecodeBlockProgressiveAc(ArithmeticDecodingComponent component, ref Block8x8 block, ref ArithmeticDecodingTable? acTable) { ref JpegBitReader reader = ref this.scanBuffer; ref short blockDataRef = ref Unsafe.As(ref block); - ArithmeticStatistics acStatistics = component.AcStatistics; + ArithmeticStatistics? acStatistics = component.AcStatistics; if (acStatistics == null || acTable == null) { JpegThrowHelper.ThrowInvalidImageContentException("AC table is missing"); @@ -802,7 +844,7 @@ private void DecodeBlockProgressiveAc(ArithmeticDecodingComponent component, ref for (int k = start; k <= end; k++) { - ref byte st = ref acStatistics.GetReference(3 * (k - 1)); + ref byte st = ref acStatistics!.GetReference(3 * (k - 1)); if (this.DecodeBinaryDecision(ref reader, ref st) != 0) { break; @@ -830,7 +872,7 @@ private void DecodeBlockProgressiveAc(ArithmeticDecodingComponent component, ref if (this.DecodeBinaryDecision(ref reader, ref st) != 0) { m <<= 1; - st = ref acStatistics.GetReference(k <= acTable.AcKx ? 189 : 217); + st = ref acStatistics.GetReference(k <= acTable!.AcKx ? 189 : 217); while (this.DecodeBinaryDecision(ref reader, ref st) != 0) { if ((m <<= 1) == 0x8000) @@ -871,7 +913,7 @@ private void DecodeBlockProgressiveAc(ArithmeticDecodingComponent component, ref } } - private void ReadBlockProgressiveAcRefined(ArithmeticStatistics acStatistics, ref short blockDataRef) + private void ReadBlockProgressiveAcRefined(ArithmeticStatistics? acStatistics, ref short blockDataRef) { ref JpegBitReader reader = ref this.scanBuffer; int start = this.SpectralStart; @@ -892,7 +934,7 @@ private void ReadBlockProgressiveAcRefined(ArithmeticStatistics acStatistics, re for (int k = start; k <= end; k++) { - ref byte st = ref acStatistics.GetReference(3 * (k - 1)); + ref byte st = ref acStatistics!.GetReference(3 * (k - 1)); if (k > kex) { if (this.DecodeBinaryDecision(ref reader, ref st) != 0) @@ -935,8 +977,8 @@ private void ReadBlockProgressiveAcRefined(ArithmeticStatistics acStatistics, re private void DecodeBlockBaseline( ArithmeticDecodingComponent component, ref Block8x8 destinationBlock, - ref ArithmeticDecodingTable acTable, - ref ArithmeticDecodingTable dcTable) + ref ArithmeticDecodingTable? acTable, + ref ArithmeticDecodingTable? dcTable) { if (acTable is null) { @@ -954,7 +996,7 @@ private void DecodeBlockBaseline( // Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients. // Table F.4: Point to statistics bin S0 for DC coefficient coding. - ref byte st = ref Unsafe.Add(ref component.DcStatistics.GetReference(), component.DcContext); + ref byte st = ref Unsafe.Add(ref component.DcStatistics!.GetReference(), component.DcContext); /* Figure F.19: Decode_DC_DIFF */ if (this.DecodeBinaryDecision(ref reader, ref st) == 0) @@ -986,7 +1028,7 @@ private void DecodeBlockBaseline( } // Section F.1.4.4.1.2: Establish dc_context conditioning category. - if (m < (int)((1L << dcTable.DcL) >> 1)) + if (m < (int)((1L << dcTable!.DcL) >> 1)) { component.DcContext = 0; // zero diff category } @@ -1023,11 +1065,11 @@ private void DecodeBlockBaseline( destinationRef = (short)component.DcPredictor; // Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients. - ArithmeticStatistics acStatistics = component.AcStatistics; + ArithmeticStatistics? acStatistics = component.AcStatistics; for (int k = 1; k <= 63; k++) { - st = ref acStatistics.GetReference(3 * (k - 1)); + st = ref acStatistics!.GetReference(3 * (k - 1)); if (this.DecodeBinaryDecision(ref reader, ref st) != 0) { // EOB flag. @@ -1056,7 +1098,7 @@ private void DecodeBlockBaseline( if (this.DecodeBinaryDecision(ref reader, ref st) != 0) { m <<= 1; - st = ref acStatistics.GetReference(k <= acTable.AcKx ? 189 : 217); + st = ref acStatistics.GetReference(k <= acTable!.AcKx ? 189 : 217); while (this.DecodeBinaryDecision(ref reader, ref st) != 0) { if ((m <<= 1) == 0x8000) @@ -1106,7 +1148,7 @@ private bool HandleRestart() this.todo = this.restartInterval; - foreach (ArithmeticDecodingComponent component in this.components) + foreach (ArithmeticDecodingComponent component in this.components!) { component.DcPredictor = 0; component.DcContext = 0; @@ -1136,9 +1178,12 @@ private bool HandleRestart() [MethodImpl(InliningOptions.ShortMethod)] private void Reset() { - for (int i = 0; i < this.components.Length; i++) + for (int i = 0; i < this.components?.Length; i++) { - ArithmeticDecodingComponent component = this.components[i] as ArithmeticDecodingComponent; + ArithmeticDecodingComponent? component = this.components[i] as ArithmeticDecodingComponent; + + ArgumentNullException.ThrowIfNull(component); + component.DcPredictor = 0; } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/ComponentProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/ComponentProcessor.cs index f0cc4d5e82..fdbbf5beb8 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/ComponentProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/ComponentProcessor.cs @@ -44,7 +44,7 @@ public ComponentProcessor(MemoryAllocator memoryAllocator, JpegFrame frame, Size /// public void ClearSpectralBuffers() { - Buffer2D spectralBlocks = this.Component.SpectralBlocks; + Buffer2D spectralBlocks = this.Component.SpectralBlocks!; for (int i = 0; i < spectralBlocks.Height; i++) { spectralBlocks.DangerousGetRowSpan(i).Clear(); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DirectComponentProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DirectComponentProcessor.cs index 79e25a67a9..bfa6b9a6a7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DirectComponentProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DirectComponentProcessor.cs @@ -15,13 +15,15 @@ internal sealed class DirectComponentProcessor : ComponentProcessor public DirectComponentProcessor(MemoryAllocator memoryAllocator, JpegFrame frame, IRawJpegData rawJpeg, Size postProcessorBufferSize, IJpegComponent component) : base(memoryAllocator, frame, postProcessorBufferSize, component, blockSize: 8) { + ArgumentNullException.ThrowIfNull(rawJpeg.QuantizationTables); + this.dequantizationTable = rawJpeg.QuantizationTables[component.QuantizationTableIndex]; FloatingPointDCT.AdjustToIDCT(ref this.dequantizationTable); } public override void CopyBlocksToColorBuffer(int spectralStep) { - Buffer2D spectralBuffer = this.Component.SpectralBlocks; + Buffer2D spectralBuffer = this.Component.SpectralBlocks!; float maximumValue = this.Frame.MaxColorChannelValue; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor2.cs index 51d8d03593..fc84abc31c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor2.cs @@ -16,13 +16,15 @@ internal sealed class DownScalingComponentProcessor2 : ComponentProcessor public DownScalingComponentProcessor2(MemoryAllocator memoryAllocator, JpegFrame frame, IRawJpegData rawJpeg, Size postProcessorBufferSize, IJpegComponent component) : base(memoryAllocator, frame, postProcessorBufferSize, component, 4) { + ArgumentNullException.ThrowIfNull(rawJpeg.QuantizationTables); + this.dequantizationTable = rawJpeg.QuantizationTables[component.QuantizationTableIndex]; ScaledFloatingPointDCT.AdjustToIDCT(ref this.dequantizationTable); } public override void CopyBlocksToColorBuffer(int spectralStep) { - Buffer2D spectralBuffer = this.Component.SpectralBlocks; + Buffer2D? spectralBuffer = this.Component.SpectralBlocks; float maximumValue = this.Frame.MaxColorChannelValue; float normalizationValue = MathF.Ceiling(maximumValue / 2); @@ -41,7 +43,7 @@ public override void CopyBlocksToColorBuffer(int spectralStep) int yBuffer = y * this.BlockAreaSize.Height; Span colorBufferRow = this.ColorBuffer.DangerousGetRowSpan(yBuffer); - Span blockRow = spectralBuffer.DangerousGetRowSpan(yBlockStart + y); + Span blockRow = spectralBuffer!.DangerousGetRowSpan(yBlockStart + y); for (int xBlock = 0; xBlock < spectralBuffer.Width; xBlock++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor4.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor4.cs index b8a40f53b1..80e70e8bec 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor4.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor4.cs @@ -16,13 +16,15 @@ internal sealed class DownScalingComponentProcessor4 : ComponentProcessor public DownScalingComponentProcessor4(MemoryAllocator memoryAllocator, JpegFrame frame, IRawJpegData rawJpeg, Size postProcessorBufferSize, IJpegComponent component) : base(memoryAllocator, frame, postProcessorBufferSize, component, 2) { + ArgumentNullException.ThrowIfNull(rawJpeg.QuantizationTables); + this.dequantizationTable = rawJpeg.QuantizationTables[component.QuantizationTableIndex]; ScaledFloatingPointDCT.AdjustToIDCT(ref this.dequantizationTable); } public override void CopyBlocksToColorBuffer(int spectralStep) { - Buffer2D spectralBuffer = this.Component.SpectralBlocks; + Buffer2D? spectralBuffer = this.Component.SpectralBlocks; float maximumValue = this.Frame.MaxColorChannelValue; float normalizationValue = MathF.Ceiling(maximumValue / 2); @@ -41,7 +43,7 @@ public override void CopyBlocksToColorBuffer(int spectralStep) int yBuffer = y * this.BlockAreaSize.Height; Span colorBufferRow = this.ColorBuffer.DangerousGetRowSpan(yBuffer); - Span blockRow = spectralBuffer.DangerousGetRowSpan(yBlockStart + y); + Span blockRow = spectralBuffer!.DangerousGetRowSpan(yBlockStart + y); for (int xBlock = 0; xBlock < spectralBuffer.Width; xBlock++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor8.cs index 121b745465..7f313613e0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ComponentProcessors/DownScalingComponentProcessor8.cs @@ -15,11 +15,14 @@ internal sealed class DownScalingComponentProcessor8 : ComponentProcessor public DownScalingComponentProcessor8(MemoryAllocator memoryAllocator, JpegFrame frame, IRawJpegData rawJpeg, Size postProcessorBufferSize, IJpegComponent component) : base(memoryAllocator, frame, postProcessorBufferSize, component, 1) - => this.dcDequantizatizer = 0.125f * rawJpeg.QuantizationTables[component.QuantizationTableIndex][0]; + { + ArgumentNullException.ThrowIfNull(rawJpeg.QuantizationTables); + this.dcDequantizatizer = 0.125f * rawJpeg.QuantizationTables[component.QuantizationTableIndex][0]; + } public override void CopyBlocksToColorBuffer(int spectralStep) { - Buffer2D spectralBuffer = this.Component.SpectralBlocks; + Buffer2D? spectralBuffer = this.Component.SpectralBlocks; float maximumValue = this.Frame.MaxColorChannelValue; float normalizationValue = MathF.Ceiling(maximumValue / 2); @@ -36,7 +39,7 @@ public override void CopyBlocksToColorBuffer(int spectralStep) int yBuffer = y * this.BlockAreaSize.Height; Span colorBufferRow = this.ColorBuffer.DangerousGetRowSpan(yBuffer); - Span blockRow = spectralBuffer.DangerousGetRowSpan(yBlockStart + y); + Span blockRow = spectralBuffer!.DangerousGetRowSpan(yBlockStart + y); for (int xBlock = 0; xBlock < spectralBuffer.Width; xBlock++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs index 91abce4d74..07d897ca74 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanDecoder.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.IO; @@ -19,12 +20,12 @@ internal class HuffmanScanDecoder : IJpegScanDecoder /// /// instance containing decoding-related information. /// - private JpegFrame frame; + private JpegFrame? frame; /// /// Shortcut for .Components. /// - private IJpegComponent[] components; + private IJpegComponent[]? components; /// /// Number of component in the current scan. @@ -58,7 +59,7 @@ internal class HuffmanScanDecoder : IJpegScanDecoder private JpegBitReader scanBuffer; - private readonly SpectralConverter spectralConverter; + private readonly SpectralConverter? spectralConverter; private readonly CancellationToken cancellationToken; @@ -70,7 +71,7 @@ internal class HuffmanScanDecoder : IJpegScanDecoder /// The token to monitor cancellation. public HuffmanScanDecoder( BufferedReadStream stream, - SpectralConverter converter, + SpectralConverter? converter, CancellationToken cancellationToken) { this.stream = stream; @@ -116,6 +117,8 @@ public void ParseEntropyCodedData(int scanComponentCount) this.scanBuffer = new JpegBitReader(this.stream); + ArgumentNullException.ThrowIfNull(this.frame); + this.frame.AllocateComponents(); if (!this.frame.Progressive) @@ -134,27 +137,32 @@ public void ParseEntropyCodedData(int scanComponentCount) } /// + [MemberNotNull(nameof(frame))] public void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) { this.frame = frame; this.components = frame.Components; - this.spectralConverter.InjectFrameData(frame, jpegData); + this.spectralConverter?.InjectFrameData(frame, jpegData); } private void ParseBaselineData() { if (this.scanComponentCount != 1) { - this.spectralConverter.PrepareForDecoding(); + this.spectralConverter?.PrepareForDecoding(); this.ParseBaselineDataInterleaved(); - this.spectralConverter.CommitConversion(); + this.spectralConverter?.CommitConversion(); + } + else if (this.frame is null) + { + ArgumentNullException.ThrowIfNull(this.frame); } else if (this.frame.ComponentCount == 1) { - this.spectralConverter.PrepareForDecoding(); + this.spectralConverter?.PrepareForDecoding(); this.ParseBaselineDataSingleComponent(); - this.spectralConverter.CommitConversion(); + this.spectralConverter?.CommitConversion(); } else { @@ -165,6 +173,8 @@ private void ParseBaselineData() private void ParseBaselineDataInterleaved() { int mcu = 0; + ArgumentNullException.ThrowIfNull(this.frame); + int mcusPerColumn = this.frame.McusPerColumn; int mcusPerLine = this.frame.McusPerLine; ref JpegBitReader buffer = ref this.scanBuffer; @@ -180,8 +190,11 @@ private void ParseBaselineDataInterleaved() int mcuCol = mcu % mcusPerLine; for (int k = 0; k < this.scanComponentCount; k++) { + ArgumentNullException.ThrowIfNull(this.frame.ComponentOrder); int order = this.frame.ComponentOrder[k]; - var component = this.components[order] as JpegComponent; + JpegComponent? component = this.components?[order] as JpegComponent; + + ArgumentNullException.ThrowIfNull(component); ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DcTableId]; ref HuffmanTable acHuffmanTable = ref this.acHuffmanTables[component.AcTableId]; @@ -193,7 +206,7 @@ private void ParseBaselineDataInterleaved() // by the basic H and V specified for the component for (int y = 0; y < v; y++) { - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(y); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(y); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int x = 0; x < h; x++) @@ -202,7 +215,7 @@ private void ParseBaselineDataInterleaved() { // It is very likely that some spectral data was decoded before we've encountered 'end of scan' // so we need to decode what's left and return (or maybe throw?) - this.spectralConverter.ConvertStrideBaseline(); + this.spectralConverter?.ConvertStrideBaseline(); return; } @@ -224,15 +237,19 @@ ref Unsafe.Add(ref blockRef, blockCol), } // Convert from spectral to actual pixels via given converter - this.spectralConverter.ConvertStrideBaseline(); + this.spectralConverter?.ConvertStrideBaseline(); } } private void ParseBaselineDataNonInterleaved() { - var component = this.components[this.frame.ComponentOrder[0]] as JpegComponent; + ArgumentNullException.ThrowIfNull(this.frame); + ArgumentNullException.ThrowIfNull(this.frame.ComponentOrder); + JpegComponent? component = this.components?[this.frame.ComponentOrder[0]] as JpegComponent; ref JpegBitReader buffer = ref this.scanBuffer; + ArgumentNullException.ThrowIfNull(component); + int w = component.WidthInBlocks; int h = component.HeightInBlocks; @@ -242,7 +259,7 @@ private void ParseBaselineDataNonInterleaved() for (int j = 0; j < h; j++) { this.cancellationToken.ThrowIfCancellationRequested(); - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(j); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int i = 0; i < w; i++) @@ -265,7 +282,12 @@ ref Unsafe.Add(ref blockRef, i), private void ParseBaselineDataSingleComponent() { - JpegComponent component = this.frame.Components[0]; + ArgumentNullException.ThrowIfNull(this.frame); + + JpegComponent? component = this.frame.Components?[0]; + + ArgumentNullException.ThrowIfNull(component); + int mcuLines = this.frame.McusPerColumn; int w = component.WidthInBlocks; int h = component.SamplingFactors.Height; @@ -281,7 +303,7 @@ private void ParseBaselineDataSingleComponent() // decode from binary to spectral for (int j = 0; j < h; j++) { - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(j); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int k = 0; k < w; k++) @@ -290,7 +312,7 @@ private void ParseBaselineDataSingleComponent() { // It is very likely that some spectral data was decoded before we've encountered 'end of scan' // so we need to decode what's left and return (or maybe throw?) - this.spectralConverter.ConvertStrideBaseline(); + this.spectralConverter?.ConvertStrideBaseline(); return; } @@ -305,7 +327,7 @@ ref Unsafe.Add(ref blockRef, k), } // Convert from spectral to actual pixels via given converter - this.spectralConverter.ConvertStrideBaseline(); + this.spectralConverter?.ConvertStrideBaseline(); } } @@ -377,6 +399,8 @@ private void ParseProgressiveDataInterleaved() { // Interleaved int mcu = 0; + ArgumentNullException.ThrowIfNull(this.frame); + int mcusPerColumn = this.frame.McusPerColumn; int mcusPerLine = this.frame.McusPerLine; ref JpegBitReader buffer = ref this.scanBuffer; @@ -390,8 +414,12 @@ private void ParseProgressiveDataInterleaved() int mcuCol = mcu % mcusPerLine; for (int k = 0; k < this.scanComponentCount; k++) { + ArgumentNullException.ThrowIfNull(this.frame.ComponentOrder); int order = this.frame.ComponentOrder[k]; - var component = this.components[order] as JpegComponent; + JpegComponent? component = this.components?[order] as JpegComponent; + + ArgumentNullException.ThrowIfNull(component); + ref HuffmanTable dcHuffmanTable = ref this.dcHuffmanTables[component.DcTableId]; int h = component.HorizontalSamplingFactor; @@ -402,7 +430,7 @@ private void ParseProgressiveDataInterleaved() for (int y = 0; y < v; y++) { int blockRow = (mcuRow * v) + y; - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(blockRow); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(blockRow); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int x = 0; x < h; x++) @@ -432,9 +460,14 @@ ref Unsafe.Add(ref blockRef, blockCol), private void ParseProgressiveDataNonInterleaved() { - var component = this.components[this.frame.ComponentOrder[0]] as JpegComponent; + ArgumentNullException.ThrowIfNull(this.frame); + + ArgumentNullException.ThrowIfNull(this.frame.ComponentOrder); + JpegComponent? component = this.components?[this.frame.ComponentOrder[0]] as JpegComponent; ref JpegBitReader buffer = ref this.scanBuffer; + ArgumentNullException.ThrowIfNull(component); + int w = component.WidthInBlocks; int h = component.HeightInBlocks; @@ -446,7 +479,7 @@ private void ParseProgressiveDataNonInterleaved() { this.cancellationToken.ThrowIfCancellationRequested(); - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(j); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int i = 0; i < w; i++) @@ -473,7 +506,7 @@ ref Unsafe.Add(ref blockRef, i), { this.cancellationToken.ThrowIfCancellationRequested(); - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(j); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (int i = 0; i < w; i++) @@ -727,7 +760,7 @@ private void DecodeBlockProgressiveACRefined(ref short blockDataRef, ref Huffman [MethodImpl(InliningOptions.ShortMethod)] private void Reset() { - for (int i = 0; i < this.components.Length; i++) + for (int i = 0; i < this.components?.Length; i++) { this.components[i].DcPredictor = 0; } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/IJpegComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/IJpegComponent.cs index 168e351bdf..78a5410db5 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/IJpegComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/IJpegComponent.cs @@ -58,7 +58,7 @@ internal interface IJpegComponent /// Gets the storing the "raw" frequency-domain decoded + unzigged blocks. /// We need to apply IDCT and dequantization to transform them into color-space blocks. /// - Buffer2D SpectralBlocks { get; } + Buffer2D? SpectralBlocks { get; } /// /// Gets or sets DC coefficient predictor. diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs index fcb98b41b3..7cb0a53881 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs @@ -16,10 +16,10 @@ internal interface IRawJpegData : IDisposable /// /// Gets the components. /// - JpegComponent[] Components { get; } + JpegComponent[]? Components { get; } /// /// Gets the quantization tables, in natural order. /// - Block8x8F[] QuantizationTables { get; } + Block8x8F[]? QuantizationTables { get; } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs index 3d015f4d94..42dcf7200a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs @@ -109,7 +109,7 @@ public bool Equals(JFifMarker other) && this.YDensity == other.YDensity; /// - public override bool Equals(object obj) => obj is JFifMarker other && this.Equals(other); + public override bool Equals(object? obj) => obj is JFifMarker other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs index 5741c9536f..334c9d7eb4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs @@ -47,7 +47,7 @@ public JpegComponent(MemoryAllocator memoryAllocator, JpegFrame frame, byte id, public int VerticalSamplingFactor { get; } /// - public Buffer2D SpectralBlocks { get; private set; } + public Buffer2D? SpectralBlocks { get; private set; } /// public Size SubSamplingDivisors { get; private set; } @@ -90,7 +90,6 @@ public JpegComponent(MemoryAllocator memoryAllocator, JpegFrame frame, byte id, public void Dispose() { this.SpectralBlocks?.Dispose(); - this.SpectralBlocks = null; } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs index 9937cc8e20..8154b0a5eb 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegFrame.cs @@ -73,18 +73,18 @@ public JpegFrame(JpegFileMarker sofMarker, byte precision, int width, int height /// /// Gets or sets the component id collection. /// - public byte[] ComponentIds { get; set; } + public byte[]? ComponentIds { get; set; } /// /// Gets or sets the order in which to process the components. /// in interleaved mode. /// - public byte[] ComponentOrder { get; set; } + public byte[]? ComponentOrder { get; set; } /// /// Gets or sets the frame component collection. /// - public JpegComponent[] Components { get; set; } + public JpegComponent[]? Components { get; set; } /// /// Gets or sets the number of MCU's per line. @@ -115,8 +115,6 @@ public void Dispose() { this.Components[i]?.Dispose(); } - - this.Components = null; } } @@ -132,8 +130,8 @@ public void Init(int maxSubFactorH, int maxSubFactorV) for (int i = 0; i < this.ComponentCount; i++) { - IJpegComponent component = this.Components[i]; - component.Init(maxSubFactorH, maxSubFactorV); + IJpegComponent? component = this.Components?[i]; + component?.Init(maxSubFactorH, maxSubFactorV); } } @@ -142,8 +140,8 @@ public void AllocateComponents() bool fullScan = this.Progressive || !this.Interleaved; for (int i = 0; i < this.ComponentCount; i++) { - IJpegComponent component = this.Components[i]; - component.AllocateSpectral(fullScan); + IJpegComponent? component = this.Components?[i]; + component?.AllocateSpectral(fullScan); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs index 8240a74587..13b18c928c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs @@ -27,34 +27,34 @@ internal class SpectralConverter : SpectralConverter, IDisposable /// private readonly Configuration configuration; - private JpegFrame frame; + private JpegFrame? frame; - private IRawJpegData jpegData; + private IRawJpegData? jpegData; /// /// Jpeg component converters from decompressed spectral to color data. /// - private ComponentProcessor[] componentProcessors; + private ComponentProcessor[]? componentProcessors; /// /// Color converter from jpeg color space to target pixel color space. /// - private JpegColorConverterBase colorConverter; + private JpegColorConverterBase? colorConverter; /// /// Intermediate buffer of RGB components used in color conversion. /// - private IMemoryOwner rgbBuffer; + private IMemoryOwner? rgbBuffer; /// /// Proxy buffer used in packing from RGB to target TPixel pixels. /// - private IMemoryOwner paddedProxyPixelRow; + private IMemoryOwner? paddedProxyPixelRow; /// /// Resulting 2D pixel buffer. /// - private Buffer2D pixelBuffer; + private Buffer2D? pixelBuffer; /// /// How many pixel rows are processed in one 'stride'. @@ -101,6 +101,8 @@ public Buffer2D GetPixelBuffer(CancellationToken cancellationToken) { this.PrepareForDecoding(); + ArgumentNullException.ThrowIfNull(this.pixelBuffer); + int steps = (int)Math.Ceiling(this.pixelBuffer.Height / (float)this.pixelRowsPerStep); for (int step = 0; step < steps; step++) @@ -110,9 +112,9 @@ public Buffer2D GetPixelBuffer(CancellationToken cancellationToken) } } - Buffer2D buffer = this.pixelBuffer; + Buffer2D? buffer = this.pixelBuffer; this.pixelBuffer = null; - return buffer; + return buffer!; } /// @@ -121,6 +123,9 @@ public Buffer2D GetPixelBuffer(CancellationToken cancellationToken) /// Spectral stride index. private void ConvertStride(int spectralStep) { + ArgumentNullException.ThrowIfNull(this.pixelBuffer); + ArgumentNullException.ThrowIfNull(this.componentProcessors); + int maxY = Math.Min(this.pixelBuffer.Height, this.pixelRowCounter + this.pixelRowsPerStep); for (int i = 0; i < this.componentProcessors.Length; i++) @@ -136,9 +141,11 @@ private void ConvertStride(int spectralStep) var values = new JpegColorConverterBase.ComponentValues(this.componentProcessors, y); + ArgumentNullException.ThrowIfNull(this.colorConverter); this.colorConverter.ConvertToRgbInplace(values); values = values.Slice(0, width); // slice away Jpeg padding + ArgumentNullException.ThrowIfNull(this.rgbBuffer); Span r = this.rgbBuffer.Slice(0, width); Span g = this.rgbBuffer.Slice(width, width); Span b = this.rgbBuffer.Slice(width * 2, width); @@ -156,6 +163,7 @@ private void ConvertStride(int spectralStep) } else { + ArgumentNullException.ThrowIfNull(this.paddedProxyPixelRow); Span proxyRow = this.paddedProxyPixelRow.GetSpan(); PixelOperations.Instance.PackFromRgbPlanes(r, g, b, proxyRow); proxyRow[..width].CopyTo(this.pixelBuffer.DangerousGetRowSpan(yy)); @@ -180,6 +188,8 @@ public override void PrepareForDecoding() MemoryAllocator allocator = this.configuration.MemoryAllocator; // color converter from RGB to TPixel + ArgumentNullException.ThrowIfNull(this.frame); + ArgumentNullException.ThrowIfNull(this.jpegData); JpegColorConverterBase converter = this.GetColorConverter(this.frame, this.jpegData); this.colorConverter = converter; @@ -187,6 +197,8 @@ public override void PrepareForDecoding() Size pixelSize = CalculateResultingImageSize(this.frame.PixelSize, this.targetSize, out int blockPixelSize); // iteration data + ArgumentNullException.ThrowIfNull(this.frame.Components); + int majorBlockWidth = this.frame.Components.Max((component) => component.SizeInBlocks.Width); int majorVerticalSamplingFactor = this.frame.Components.Max((component) => component.SamplingFactors.Height); @@ -217,6 +229,8 @@ public override void ConvertStrideBaseline() // Note that zero passing eliminates extra virtual call this.ConvertStride(spectralStep: 0); + ArgumentNullException.ThrowIfNull(this.componentProcessors); + foreach (ComponentProcessor cpp in this.componentProcessors) { cpp.ClearSpectralBuffers(); @@ -226,6 +240,9 @@ public override void ConvertStrideBaseline() protected ComponentProcessor[] CreateComponentProcessors(JpegFrame frame, IRawJpegData jpegData, int blockPixelSize, Size processorBufferSize) { MemoryAllocator allocator = this.configuration.MemoryAllocator; + + ArgumentNullException.ThrowIfNull(frame.Components); + var componentProcessors = new ComponentProcessor[frame.Components.Length]; for (int i = 0; i < componentProcessors.Length; i++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/Component.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/Component.cs index 3049ab2c40..20d34f77e3 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/Component.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/Component.cs @@ -38,7 +38,7 @@ public Component(MemoryAllocator memoryAllocator, int horizontalFactor, int vert /// public int VerticalSamplingFactor { get; } - public Buffer2D SpectralBlocks { get; private set; } + public Buffer2D? SpectralBlocks { get; private set; } public Size SubSamplingDivisors { get; private set; } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs index 2bc1405509..fb693a48ac 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs @@ -41,7 +41,7 @@ public ComponentProcessor(MemoryAllocator memoryAllocator, Component component, public void CopyColorBufferToBlocks(int spectralStep) { - Buffer2D spectralBuffer = this.component.SpectralBlocks; + Buffer2D? spectralBuffer = this.component.SpectralBlocks; int destAreaStride = this.ColorBuffer.Width; int yBlockStart = spectralStep * this.component.SamplingFactors.Height; @@ -60,7 +60,7 @@ public void CopyColorBufferToBlocks(int spectralStep) { int yBuffer = y * this.blockAreaSize.Height; Span colorBufferRow = this.ColorBuffer.DangerousGetRowSpan(yBuffer); - Span blockRow = spectralBuffer.DangerousGetRowSpan(yBlockStart + y); + Span blockRow = spectralBuffer!.DangerousGetRowSpan(yBlockStart + y); for (int xBlock = 0; xBlock < spectralBuffer.Width; xBlock++) { // load 8x8 block from 8 pixel strides diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs index 8edbc3c407..c6aaa15694 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs @@ -177,7 +177,7 @@ public void EncodeScanBaselineSingleComponent(Component component, Spect converter.ConvertStrideBaseline(); // Encode spectral to binary - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(y: 0); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(y: 0); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (nint k = 0; k < w; k++) @@ -216,7 +216,7 @@ public void EncodeScanBaseline(Component component, CancellationToken cancellati cancellationToken.ThrowIfCancellationRequested(); // Encode spectral to binary - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(y: i); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(y: i); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (nint k = 0; k < w; k++) @@ -278,7 +278,7 @@ private void EncodeScanBaselineInterleaved(JpegFrame frame, SpectralConv // by the basic H and V specified for the component for (int y = 0; y < v; y++) { - Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(y); + Span blockSpan = component.SpectralBlocks!.DangerousGetRowSpan(y); ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); for (nint x = 0; x < h; x++) @@ -329,9 +329,9 @@ private void EncodeThreeComponentBaselineInterleavedScanNoSubsampling(Jp ref HuffmanLut c2dcHuffmanTable = ref this.dcHuffmanTables[c2.DcTableId]; ref HuffmanLut c2acHuffmanTable = ref this.acHuffmanTables[c2.AcTableId]; - ref Block8x8 c0BlockRef = ref MemoryMarshal.GetReference(c0.SpectralBlocks.DangerousGetRowSpan(y: 0)); - ref Block8x8 c1BlockRef = ref MemoryMarshal.GetReference(c1.SpectralBlocks.DangerousGetRowSpan(y: 0)); - ref Block8x8 c2BlockRef = ref MemoryMarshal.GetReference(c2.SpectralBlocks.DangerousGetRowSpan(y: 0)); + ref Block8x8 c0BlockRef = ref MemoryMarshal.GetReference(c0.SpectralBlocks!.DangerousGetRowSpan(y: 0)); + ref Block8x8 c1BlockRef = ref MemoryMarshal.GetReference(c1.SpectralBlocks!.DangerousGetRowSpan(y: 0)); + ref Block8x8 c2BlockRef = ref MemoryMarshal.GetReference(c2.SpectralBlocks!.DangerousGetRowSpan(y: 0)); for (nint j = 0; j < mcusPerColumn; j++) { diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 11a9bc5578..eb6e0def6f 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Common.Helpers; @@ -49,7 +50,7 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals /// /// Contains exif data. /// - private byte[] exifData; + private byte[]? exifData; /// /// Whether the image has an ICC marker. @@ -59,7 +60,7 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals /// /// Contains ICC data. /// - private byte[] iccData; + private byte[]? iccData; /// /// Whether the image has a IPTC data. @@ -69,7 +70,7 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals /// /// Contains IPTC data. /// - private byte[] iptcData; + private byte[]? iptcData; /// /// Whether the image has a XMP data. @@ -79,7 +80,7 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals /// /// Contains XMP data. /// - private byte[] xmpData; + private byte[]? xmpData; /// /// Whether the image has a APP14 adobe marker. This is needed to determine image encoded colorspace. @@ -99,12 +100,12 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals /// /// Scan decoder. /// - private IJpegScanDecoder scanDecoder; + private IJpegScanDecoder? scanDecoder; /// /// The arithmetic decoding tables. /// - private List arithmeticDecodingTables; + private List? arithmeticDecodingTables; /// /// The restart interval. @@ -142,17 +143,17 @@ public JpegDecoderCore(JpegDecoderOptions options) public DecoderOptions Options { get; } /// - public Size Dimensions => this.Frame.PixelSize; + public Size? Dimensions => this.Frame?.PixelSize; /// /// Gets the frame /// - public JpegFrame Frame { get; private set; } + public JpegFrame? Frame { get; private set; } /// /// Gets the decoded by this decoder instance. /// - public ImageMetadata Metadata { get; private set; } + public ImageMetadata? Metadata { get; private set; } /// public JpegColorSpace ColorSpace { get; private set; } @@ -160,13 +161,13 @@ public JpegDecoderCore(JpegDecoderOptions options) /// /// Gets the components. /// - public JpegComponent[] Components => this.Frame.Components; + public JpegComponent[]? Components => this.Frame?.Components; /// - JpegComponent[] IRawJpegData.Components => this.Components; + JpegComponent[]? IRawJpegData.Components => this.Components; /// - public Block8x8F[] QuantizationTables { get; private set; } + public Block8x8F[]? QuantizationTables { get; private set; } /// /// Finds the next file marker within the byte stream. @@ -217,6 +218,8 @@ public Image Decode(BufferedReadStream stream, CancellationToken this.InitXmpProfile(); this.InitDerivedMetadataProperties(); + ArgumentNullException.ThrowIfNull(this.Metadata); + return new Image( this.configuration, spectralConverter.GetPixelBuffer(cancellationToken), @@ -233,7 +236,9 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella this.InitXmpProfile(); this.InitDerivedMetadataProperties(); - Size pixelSize = this.Frame.PixelSize; + Size pixelSize = this.Frame!.PixelSize; + ArgumentNullException.ThrowIfNull(this.Metadata); + return new ImageInfo(new PixelTypeInfo(this.Frame.BitsPerPixel), pixelSize.Width, pixelSize.Height, this.Metadata); } @@ -320,7 +325,7 @@ public void LoadTables(byte[] tableBytes, IJpegScanDecoder scanDecoder) /// The input stream. /// The spectral converter to use. /// The token to monitor cancellation. - internal void ParseStream(BufferedReadStream stream, SpectralConverter spectralConverter, CancellationToken cancellationToken) + internal void ParseStream(BufferedReadStream stream, SpectralConverter? spectralConverter, CancellationToken cancellationToken) { bool metadataOnly = spectralConverter == null; @@ -494,7 +499,7 @@ internal void ParseStream(BufferedReadStream stream, SpectralConverter spectralC fileMarker = FindNextFileMarker(stream); } - this.Metadata.GetJpegMetadata().Interleaved = this.Frame.Interleaved; + this.Metadata.GetJpegMetadata().Interleaved = this.Frame?.Interleaved; } /// @@ -585,31 +590,31 @@ private JpegEncodingColor DeduceJpegColorType() return JpegEncodingColor.Rgb; case JpegColorSpace.YCbCr: - if (this.Frame.Components[0].HorizontalSamplingFactor == 1 && this.Frame.Components[0].VerticalSamplingFactor == 1 && + if (this.Frame?.Components?[0].HorizontalSamplingFactor == 1 && this.Frame.Components[0].VerticalSamplingFactor == 1 && this.Frame.Components[1].HorizontalSamplingFactor == 1 && this.Frame.Components[1].VerticalSamplingFactor == 1 && this.Frame.Components[2].HorizontalSamplingFactor == 1 && this.Frame.Components[2].VerticalSamplingFactor == 1) { return JpegEncodingColor.YCbCrRatio444; } - else if (this.Frame.Components[0].HorizontalSamplingFactor == 2 && this.Frame.Components[0].VerticalSamplingFactor == 1 && + else if (this.Frame?.Components?[0].HorizontalSamplingFactor == 2 && this.Frame.Components[0].VerticalSamplingFactor == 1 && this.Frame.Components[1].HorizontalSamplingFactor == 1 && this.Frame.Components[1].VerticalSamplingFactor == 1 && this.Frame.Components[2].HorizontalSamplingFactor == 1 && this.Frame.Components[2].VerticalSamplingFactor == 1) { return JpegEncodingColor.YCbCrRatio422; } - else if (this.Frame.Components[0].HorizontalSamplingFactor == 2 && this.Frame.Components[0].VerticalSamplingFactor == 2 && + else if (this.Frame?.Components?[0].HorizontalSamplingFactor == 2 && this.Frame.Components[0].VerticalSamplingFactor == 2 && this.Frame.Components[1].HorizontalSamplingFactor == 1 && this.Frame.Components[1].VerticalSamplingFactor == 1 && this.Frame.Components[2].HorizontalSamplingFactor == 1 && this.Frame.Components[2].VerticalSamplingFactor == 1) { return JpegEncodingColor.YCbCrRatio420; } - else if (this.Frame.Components[0].HorizontalSamplingFactor == 4 && this.Frame.Components[0].VerticalSamplingFactor == 1 && + else if (this.Frame?.Components?[0].HorizontalSamplingFactor == 4 && this.Frame.Components[0].VerticalSamplingFactor == 1 && this.Frame.Components[1].HorizontalSamplingFactor == 1 && this.Frame.Components[1].VerticalSamplingFactor == 1 && this.Frame.Components[2].HorizontalSamplingFactor == 1 && this.Frame.Components[2].VerticalSamplingFactor == 1) { return JpegEncodingColor.YCbCrRatio411; } - else if (this.Frame.Components[0].HorizontalSamplingFactor == 4 && this.Frame.Components[0].VerticalSamplingFactor == 2 && + else if (this.Frame?.Components?[0].HorizontalSamplingFactor == 4 && this.Frame.Components[0].VerticalSamplingFactor == 2 && this.Frame.Components[1].HorizontalSamplingFactor == 1 && this.Frame.Components[1].VerticalSamplingFactor == 1 && this.Frame.Components[2].HorizontalSamplingFactor == 1 && this.Frame.Components[2].VerticalSamplingFactor == 1) { @@ -636,6 +641,8 @@ private void InitExifProfile() { if (this.hasExif) { + ArgumentNullException.ThrowIfNull(this.Metadata); + this.Metadata.ExifProfile = new ExifProfile(this.exifData); } } @@ -650,6 +657,8 @@ private void InitIccProfile() IccProfile profile = new(this.iccData); if (profile.CheckIsValid()) { + ArgumentNullException.ThrowIfNull(this.Metadata); + this.Metadata.IccProfile = profile; } } @@ -662,6 +671,8 @@ private void InitIptcProfile() { if (this.hasIptc) { + ArgumentNullException.ThrowIfNull(this.Metadata); + this.Metadata.IptcProfile = new IptcProfile(this.iptcData); } } @@ -673,6 +684,8 @@ private void InitXmpProfile() { if (this.hasXmp) { + ArgumentNullException.ThrowIfNull(this.Metadata); + this.Metadata.XmpProfile = new XmpProfile(this.xmpData); } } @@ -684,6 +697,8 @@ private void InitDerivedMetadataProperties() { if (this.jFif.XDensity > 0 && this.jFif.YDensity > 0) { + ArgumentNullException.ThrowIfNull(this.Metadata); + this.Metadata.HorizontalResolution = this.jFif.XDensity; this.Metadata.VerticalResolution = this.jFif.YDensity; this.Metadata.ResolutionUnits = this.jFif.DensityUnits; @@ -695,16 +710,20 @@ private void InitDerivedMetadataProperties() if (horizontalValue > 0 && verticalValue > 0) { + ArgumentNullException.ThrowIfNull(this.Metadata); + this.Metadata.HorizontalResolution = horizontalValue; this.Metadata.VerticalResolution = verticalValue; - this.Metadata.ResolutionUnits = UnitConverter.ExifProfileToResolutionUnit(this.Metadata.ExifProfile); + this.Metadata.ResolutionUnits = UnitConverter.ExifProfileToResolutionUnit(this.Metadata.ExifProfile!); } } } private double GetExifResolutionValue(ExifTag tag) { - IExifValue resolution = this.Metadata.ExifProfile.GetValue(tag); + ArgumentNullException.ThrowIfNull(this.Metadata); + + IExifValue? resolution = this.Metadata.ExifProfile!.GetValue(tag); return resolution is null ? 0 : resolution.Value.ToDouble(); } @@ -951,6 +970,7 @@ private void ProcessApp13Marker(BufferedReadStream stream, int remaining) /// /// The input stream. /// The remaining bytes in the segment block. + [MemberNotNull(nameof(arithmeticDecodingTables))] private void ProcessArithmeticTable(BufferedReadStream stream, int remaining) { this.arithmeticDecodingTables ??= new List(4); @@ -1055,6 +1075,8 @@ private void ProcessApp14Marker(BufferedReadStream stream, int remaining) /// private void ProcessDefineQuantizationTablesMarker(BufferedReadStream stream, int remaining) { + ArgumentNullException.ThrowIfNull(this.Metadata); + JpegMetadata jpegMetadata = this.Metadata.GetFormatMetadata(JpegFormat.Instance); while (remaining > 0) @@ -1075,6 +1097,8 @@ private void ProcessDefineQuantizationTablesMarker(BufferedReadStream stream, in remaining--; // Decoding single 8x8 table + ArgumentNullException.ThrowIfNull(this.QuantizationTables); + ref Block8x8F table = ref this.QuantizationTables[tableIndex]; switch (tablePrecision) { @@ -1199,6 +1223,8 @@ private void ProcessStartOfFrameMarker(BufferedReadStream stream, int remaining, } this.Frame = new JpegFrame(frameMarker, precision, frameWidth, frameHeight, componentCount); + ArgumentNullException.ThrowIfNull(this.Metadata); + this.Metadata.GetJpegMetadata().Progressive = this.Frame.Progressive; remaining -= length; @@ -1280,7 +1306,7 @@ private void ProcessStartOfFrameMarker(BufferedReadStream stream, int remaining, if (!metadataOnly) { this.Frame.Init(maxH, maxV); - this.scanDecoder.InjectFrameData(this.Frame, this); + this.scanDecoder?.InjectFrameData(this.Frame, this); } } @@ -1296,7 +1322,7 @@ private void ProcessDefineHuffmanTablesMarker(BufferedReadStream stream, int rem const int codeValuesMaxByteSize = 256; const int totalBufferSize = codeLengthsByteSize + codeValuesMaxByteSize + HuffmanTable.WorkspaceByteSize; - HuffmanScanDecoder huffmanScanDecoder = this.scanDecoder as HuffmanScanDecoder; + HuffmanScanDecoder? huffmanScanDecoder = this.scanDecoder as HuffmanScanDecoder; if (huffmanScanDecoder is null) { JpegThrowHelper.ThrowInvalidImageContentException("missing huffman table data"); @@ -1396,7 +1422,7 @@ private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining) int selectorsCount = stream.ReadByte(); // Validate: 0 < count <= totalComponents - if (selectorsCount == 0 || selectorsCount > this.Frame.ComponentCount) + if (selectorsCount == 0 || selectorsCount > this.Frame?.ComponentCount) { // TODO: extract as separate method? JpegThrowHelper.ThrowInvalidImageContentException($"Invalid number of components in scan: {selectorsCount}."); @@ -1411,7 +1437,7 @@ private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining) // selectorsCount*2 bytes: component index + huffman tables indices stream.Read(this.temp, 0, selectorsBytes); - + ArgumentNullException.ThrowIfNull(this.Frame); this.Frame.Interleaved = this.Frame.ComponentCount == selectorsCount; for (int i = 0; i < selectorsBytes; i += 2) { @@ -1419,7 +1445,9 @@ private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining) int componentSelectorId = this.temp[i]; int componentIndex = -1; - for (int j = 0; j < this.Frame.ComponentIds.Length; j++) + ArgumentNullException.ThrowIfNull(this.Frame); + ArgumentNullException.ThrowIfNull(this.Frame.ComponentIds); + for (int j = 0; j < this.Frame?.ComponentIds.Length; j++) { byte id = this.Frame.ComponentIds[j]; if (componentSelectorId == id) @@ -1436,9 +1464,13 @@ private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining) JpegThrowHelper.ThrowInvalidImageContentException($"Unknown component id in scan: {componentSelectorId}."); } + ArgumentNullException.ThrowIfNull(this.Frame); + ArgumentNullException.ThrowIfNull(this.Frame.ComponentOrder); this.Frame.ComponentOrder[i / 2] = (byte)componentIndex; - IJpegComponent component = this.Frame.Components[componentIndex]; + IJpegComponent? component = this.Frame?.Components?[componentIndex]; + + ArgumentNullException.ThrowIfNull(component); // 1 byte: Huffman table selectors. // 4 bits - dc @@ -1465,7 +1497,7 @@ private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining) JpegThrowHelper.ThrowInvalidImageContentException("Not enough data to read progressive scan decoding data"); } - this.scanDecoder.SpectralStart = this.temp[0]; + this.scanDecoder!.SpectralStart = this.temp[0]; this.scanDecoder.SpectralEnd = this.temp[1]; @@ -1475,6 +1507,7 @@ private void ProcessStartOfScanMarker(BufferedReadStream stream, int remaining) if (this.scanDecoder is ArithmeticScanDecoder arithmeticScanDecoder) { + ArgumentNullException.ThrowIfNull(this.arithmeticDecodingTables); arithmeticScanDecoder.InitDecodingTables(this.arithmeticDecodingTables); } diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index 83c2e27e91..8e9536a0ae 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -31,11 +31,6 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals private readonly IJpegEncoderOptions options; - /// - /// The output stream. All attempted writes after the first error become no-ops. - /// - private Stream outputStream; - /// /// Initializes a new instance of the class. /// @@ -65,8 +60,6 @@ public void Encode(Image image, Stream stream, CancellationToken cancellationToken.ThrowIfCancellationRequested(); - this.outputStream = stream; - ImageMetadata metadata = image.Metadata; JpegMetadata jpegMetadata = metadata.GetJpegMetadata(); JpegFrameConfig frameConfig = this.GetFrameConfig(jpegMetadata); @@ -75,39 +68,39 @@ public void Encode(Image image, Stream stream, CancellationToken using var frame = new JpegFrame(image, frameConfig, interleaved); // Write the Start Of Image marker. - this.WriteStartOfImage(); + this.WriteStartOfImage(stream); // Write APP0 marker if (frameConfig.AdobeColorTransformMarkerFlag is null) { - this.WriteJfifApplicationHeader(metadata); + this.WriteJfifApplicationHeader(metadata, stream); } // Write APP14 marker with adobe color extension else { - this.WriteApp14Marker(frameConfig.AdobeColorTransformMarkerFlag.Value); + this.WriteApp14Marker(frameConfig.AdobeColorTransformMarkerFlag.Value, stream); } // Write Exif, XMP, ICC and IPTC profiles - this.WriteProfiles(metadata); + this.WriteProfiles(metadata, stream); // Write the image dimensions. - this.WriteStartOfFrame(image.Width, image.Height, frameConfig); + this.WriteStartOfFrame(image.Width, image.Height, frameConfig, stream); // Write the Huffman tables. var scanEncoder = new HuffmanScanEncoder(frame.BlocksPerMcu, stream); - this.WriteDefineHuffmanTables(frameConfig.HuffmanTables, scanEncoder); + this.WriteDefineHuffmanTables(frameConfig.HuffmanTables, scanEncoder, stream); // Write the quantization tables. - this.WriteDefineQuantizationTables(frameConfig.QuantizationTables, this.options.Quality, jpegMetadata); + this.WriteDefineQuantizationTables(frameConfig.QuantizationTables, this.options.Quality, jpegMetadata, stream); // Write scans with actual pixel data using var spectralConverter = new SpectralConverter(frame, image, this.QuantizationTables); - this.WriteHuffmanScans(frame, frameConfig, spectralConverter, scanEncoder, cancellationToken); + this.WriteHuffmanScans(frame, frameConfig, spectralConverter, scanEncoder, stream, cancellationToken); // Write the End Of Image marker. - this.WriteEndOfImageMarker(); + this.WriteEndOfImageMarker(stream); stream.Flush(); } @@ -115,20 +108,20 @@ public void Encode(Image image, Stream stream, CancellationToken /// /// Write the start of image marker. /// - private void WriteStartOfImage() + private void WriteStartOfImage(Stream outputStream) { // Markers are always prefixed with 0xff. this.buffer[0] = JpegConstants.Markers.XFF; this.buffer[1] = JpegConstants.Markers.SOI; - this.outputStream.Write(this.buffer, 0, 2); + outputStream.Write(this.buffer, 0, 2); } /// /// Writes the application header containing the JFIF identifier plus extra data. /// /// The image metadata. - private void WriteJfifApplicationHeader(ImageMetadata meta) + private void WriteJfifApplicationHeader(ImageMetadata meta, Stream outputStream) { // Write the JFIF headers this.buffer[0] = JpegConstants.Markers.XFF; @@ -166,13 +159,13 @@ private void WriteJfifApplicationHeader(ImageMetadata meta) this.buffer[16] = 0x00; // Thumbnail width this.buffer[17] = 0x00; // Thumbnail height - this.outputStream.Write(this.buffer, 0, 18); + outputStream.Write(this.buffer, 0, 18); } /// /// Writes the Define Huffman Table marker and tables. /// - private void WriteDefineHuffmanTables(JpegHuffmanTableConfig[] tableConfigs, HuffmanScanEncoder scanEncoder) + private void WriteDefineHuffmanTables(JpegHuffmanTableConfig[] tableConfigs, HuffmanScanEncoder scanEncoder, Stream outputStream) { if (tableConfigs is null) { @@ -186,15 +179,15 @@ private void WriteDefineHuffmanTables(JpegHuffmanTableConfig[] tableConfigs, Huf markerlen += 1 + 16 + tableConfigs[i].Table.Values.Length; } - this.WriteMarkerHeader(JpegConstants.Markers.DHT, markerlen); + this.WriteMarkerHeader(JpegConstants.Markers.DHT, markerlen, outputStream); for (int i = 0; i < tableConfigs.Length; i++) { JpegHuffmanTableConfig tableConfig = tableConfigs[i]; int header = (tableConfig.Class << 4) | tableConfig.DestinationIndex; - this.outputStream.WriteByte((byte)header); - this.outputStream.Write(tableConfig.Table.Count); - this.outputStream.Write(tableConfig.Table.Values); + outputStream.WriteByte((byte)header); + outputStream.Write(tableConfig.Table.Count); + outputStream.Write(tableConfig.Table.Values); scanEncoder.BuildHuffmanTable(tableConfig); } @@ -203,9 +196,9 @@ private void WriteDefineHuffmanTables(JpegHuffmanTableConfig[] tableConfigs, Huf /// /// Writes the APP14 marker to indicate the image is in RGB color space. /// - private void WriteApp14Marker(byte colorTransform) + private void WriteApp14Marker(byte colorTransform, Stream outputStream) { - this.WriteMarkerHeader(JpegConstants.Markers.APP14, 2 + Components.Decoder.AdobeMarker.Length); + this.WriteMarkerHeader(JpegConstants.Markers.APP14, 2 + Components.Decoder.AdobeMarker.Length, outputStream); // Identifier: ASCII "Adobe". this.buffer[0] = 0x41; @@ -226,14 +219,14 @@ private void WriteApp14Marker(byte colorTransform) // Color transform byte this.buffer[11] = colorTransform; - this.outputStream.Write(this.buffer.AsSpan(0, 12)); + outputStream.Write(this.buffer.AsSpan(0, 12)); } /// /// Writes the EXIF profile. /// /// The exif profile. - private void WriteExifProfile(ExifProfile exifProfile) + private void WriteExifProfile(ExifProfile? exifProfile, Stream outputStream) { if (exifProfile is null || exifProfile.Values.Count == 0) { @@ -243,7 +236,7 @@ private void WriteExifProfile(ExifProfile exifProfile) const int maxBytesApp1 = 65533; // 64k - 2 padding bytes const int maxBytesWithExifId = 65527; // Max - 6 bytes for EXIF header. - byte[] data = exifProfile.ToByteArray(); + byte[] data = exifProfile.ToByteArray()!; if (data.Length == 0) { @@ -257,9 +250,9 @@ private void WriteExifProfile(ExifProfile exifProfile) int app1Length = bytesToWrite + 2; // Write the app marker, EXIF marker, and data - this.WriteApp1Header(app1Length); - this.outputStream.Write(Components.Decoder.ProfileResolver.ExifMarker); - this.outputStream.Write(data, 0, bytesToWrite - exifMarkerLength); + this.WriteApp1Header(app1Length, outputStream); + outputStream.Write(Components.Decoder.ProfileResolver.ExifMarker); + outputStream.Write(data, 0, bytesToWrite - exifMarkerLength); remaining -= bytesToWrite; // If the exif data exceeds 64K, write it in multiple APP1 Markers @@ -268,13 +261,13 @@ private void WriteExifProfile(ExifProfile exifProfile) bytesToWrite = remaining > maxBytesWithExifId ? maxBytesWithExifId : remaining; app1Length = bytesToWrite + 2 + exifMarkerLength; - this.WriteApp1Header(app1Length); + this.WriteApp1Header(app1Length, outputStream); // Write Exif00 marker - this.outputStream.Write(Components.Decoder.ProfileResolver.ExifMarker); + outputStream.Write(Components.Decoder.ProfileResolver.ExifMarker); // Write the exif data - this.outputStream.Write(data, idx, bytesToWrite); + outputStream.Write(data, idx, bytesToWrite); remaining -= bytesToWrite; } @@ -287,7 +280,7 @@ private void WriteExifProfile(ExifProfile exifProfile) /// /// Thrown if the IPTC profile size exceeds the limit of 65533 bytes. /// - private void WriteIptcProfile(IptcProfile iptcProfile) + private void WriteIptcProfile(IptcProfile? iptcProfile, Stream outputStream) { const int maxBytes = 65533; if (iptcProfile is null || !iptcProfile.Values.Any()) @@ -296,8 +289,8 @@ private void WriteIptcProfile(IptcProfile iptcProfile) } iptcProfile.UpdateData(); - byte[] data = iptcProfile.Data; - if (data.Length == 0) + byte[]? data = iptcProfile.Data; + if (data!.Length == 0) { return; } @@ -311,15 +304,15 @@ private void WriteIptcProfile(IptcProfile iptcProfile) Components.Decoder.ProfileResolver.AdobeImageResourceBlockMarker.Length + Components.Decoder.ProfileResolver.AdobeIptcMarker.Length + 2 + 4 + data.Length; - this.WriteAppHeader(app13Length, JpegConstants.Markers.APP13); - this.outputStream.Write(Components.Decoder.ProfileResolver.AdobePhotoshopApp13Marker); - this.outputStream.Write(Components.Decoder.ProfileResolver.AdobeImageResourceBlockMarker); - this.outputStream.Write(Components.Decoder.ProfileResolver.AdobeIptcMarker); - this.outputStream.WriteByte(0); // a empty pascal string (padded to make size even) - this.outputStream.WriteByte(0); + this.WriteAppHeader(app13Length, JpegConstants.Markers.APP13, outputStream); + outputStream.Write(Components.Decoder.ProfileResolver.AdobePhotoshopApp13Marker); + outputStream.Write(Components.Decoder.ProfileResolver.AdobeImageResourceBlockMarker); + outputStream.Write(Components.Decoder.ProfileResolver.AdobeIptcMarker); + outputStream.WriteByte(0); // a empty pascal string (padded to make size even) + outputStream.WriteByte(0); BinaryPrimitives.WriteInt32BigEndian(this.buffer, data.Length); - this.outputStream.Write(this.buffer, 0, 4); - this.outputStream.Write(data, 0, data.Length); + outputStream.Write(this.buffer, 0, 4); + outputStream.Write(data, 0, data.Length); } /// @@ -329,7 +322,7 @@ private void WriteIptcProfile(IptcProfile iptcProfile) /// /// Thrown if the XMP profile size exceeds the limit of 65533 bytes. /// - private void WriteXmpProfile(XmpProfile xmpProfile) + private void WriteXmpProfile(XmpProfile? xmpProfile, Stream outputStream) { if (xmpProfile is null) { @@ -340,7 +333,7 @@ private void WriteXmpProfile(XmpProfile xmpProfile) const int maxBytes = 65533; const int maxData = maxBytes - xmpOverheadLength; - byte[] data = xmpProfile.Data; + byte[]? data = xmpProfile.Data; if (data is null || data.Length == 0) { @@ -362,9 +355,9 @@ private void WriteXmpProfile(XmpProfile xmpProfile) dataLength -= length; int app1Length = 2 + Components.Decoder.ProfileResolver.XmpMarker.Length + length; - this.WriteApp1Header(app1Length); - this.outputStream.Write(Components.Decoder.ProfileResolver.XmpMarker); - this.outputStream.Write(data, offset, length); + this.WriteApp1Header(app1Length, outputStream); + outputStream.Write(Components.Decoder.ProfileResolver.XmpMarker); + outputStream.Write(data, offset, length); offset += length; } @@ -374,22 +367,22 @@ private void WriteXmpProfile(XmpProfile xmpProfile) /// Writes the App1 header. /// /// The length of the data the app1 marker contains. - private void WriteApp1Header(int app1Length) - => this.WriteAppHeader(app1Length, JpegConstants.Markers.APP1); + private void WriteApp1Header(int app1Length, Stream outputStream) + => this.WriteAppHeader(app1Length, JpegConstants.Markers.APP1, outputStream); /// /// Writes a AppX header. /// /// The length of the data the app marker contains. /// The app marker to write. - private void WriteAppHeader(int length, byte appMarker) + private void WriteAppHeader(int length, byte appMarker, Stream outputStream) { this.buffer[0] = JpegConstants.Markers.XFF; this.buffer[1] = appMarker; this.buffer[2] = (byte)((length >> 8) & 0xFF); this.buffer[3] = (byte)(length & 0xFF); - this.outputStream.Write(this.buffer, 0, 4); + outputStream.Write(this.buffer, 0, 4); } /// @@ -399,7 +392,7 @@ private void WriteAppHeader(int length, byte appMarker) /// /// Thrown if any of the ICC profiles size exceeds the limit. /// - private void WriteIccProfile(IccProfile iccProfile) + private void WriteIccProfile(IccProfile? iccProfile, Stream outputStream) { if (iccProfile is null) { @@ -447,7 +440,7 @@ private void WriteIccProfile(IccProfile iccProfile) this.buffer[2] = (byte)((markerLength >> 8) & 0xFF); this.buffer[3] = (byte)(markerLength & 0xFF); - this.outputStream.Write(this.buffer, 0, 4); + outputStream.Write(this.buffer, 0, 4); this.buffer[0] = (byte)'I'; this.buffer[1] = (byte)'C'; @@ -464,8 +457,8 @@ private void WriteIccProfile(IccProfile iccProfile) this.buffer[12] = (byte)current; // The position within the collection. this.buffer[13] = (byte)count; // The total number of profiles. - this.outputStream.Write(this.buffer, 0, iccOverheadLength); - this.outputStream.Write(data, offset, length); + outputStream.Write(this.buffer, 0, iccOverheadLength); + outputStream.Write(data, offset, length); current++; offset += length; @@ -476,7 +469,7 @@ private void WriteIccProfile(IccProfile iccProfile) /// Writes the metadata profiles to the image. /// /// The image metadata. - private void WriteProfiles(ImageMetadata metadata) + private void WriteProfiles(ImageMetadata metadata, Stream outputStream) { if (metadata is null) { @@ -489,22 +482,22 @@ private void WriteProfiles(ImageMetadata metadata) // - APP2 ICC // - APP13 IPTC metadata.SyncProfiles(); - this.WriteExifProfile(metadata.ExifProfile); - this.WriteXmpProfile(metadata.XmpProfile); - this.WriteIccProfile(metadata.IccProfile); - this.WriteIptcProfile(metadata.IptcProfile); + this.WriteExifProfile(metadata.ExifProfile, outputStream); + this.WriteXmpProfile(metadata.XmpProfile, outputStream); + this.WriteIccProfile(metadata.IccProfile, outputStream); + this.WriteIptcProfile(metadata.IptcProfile, outputStream); } /// /// Writes the Start Of Frame (Baseline) marker. /// - private void WriteStartOfFrame(int width, int height, JpegFrameConfig frame) + private void WriteStartOfFrame(int width, int height, JpegFrameConfig frame, Stream outputStream) { JpegComponentConfig[] components = frame.Components; // Length (high byte, low byte), 8 + components * 3. int markerlen = 8 + (3 * components.Length); - this.WriteMarkerHeader(JpegConstants.Markers.SOF0, markerlen); + this.WriteMarkerHeader(JpegConstants.Markers.SOF0, markerlen, outputStream); this.buffer[0] = 8; // Data Precision. 8 for now, 12 and 16 bit jpegs not supported this.buffer[1] = (byte)(height >> 8); this.buffer[2] = (byte)(height & 0xff); // (2 bytes, Hi-Lo), must be > 0 if DNL not supported @@ -530,13 +523,13 @@ private void WriteStartOfFrame(int width, int height, JpegFrameConfig frame) bufferSpan[0] = components[i].Id; } - this.outputStream.Write(this.buffer, 0, (3 * (components.Length - 1)) + 9); + outputStream.Write(this.buffer, 0, (3 * (components.Length - 1)) + 9); } /// /// Writes the StartOfScan marker. /// - private void WriteStartOfScan(Span components) + private void WriteStartOfScan(Span components, Stream outputStream) { // Write the SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes: // - the marker length "\x00\x0c", @@ -572,37 +565,37 @@ private void WriteStartOfScan(Span components) this.buffer[sosSize - 1] = 0x00; // Ss - Start of spectral selection. this.buffer[sosSize] = 0x3f; // Se - End of spectral selection. this.buffer[sosSize + 1] = 0x00; // Ah + Ah (Successive approximation bit position high + low) - this.outputStream.Write(this.buffer, 0, sosSize + 2); + outputStream.Write(this.buffer, 0, sosSize + 2); } /// /// Writes the EndOfImage marker. /// - private void WriteEndOfImageMarker() + private void WriteEndOfImageMarker(Stream outputStream) { this.buffer[0] = JpegConstants.Markers.XFF; this.buffer[1] = JpegConstants.Markers.EOI; - this.outputStream.Write(this.buffer, 0, 2); + outputStream.Write(this.buffer, 0, 2); } /// /// Writes scans for given config. /// - private void WriteHuffmanScans(JpegFrame frame, JpegFrameConfig frameConfig, SpectralConverter spectralConverter, HuffmanScanEncoder encoder, CancellationToken cancellationToken) + private void WriteHuffmanScans(JpegFrame frame, JpegFrameConfig frameConfig, SpectralConverter spectralConverter, HuffmanScanEncoder encoder, Stream outputStream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { if (frame.Components.Length == 1) { frame.AllocateComponents(fullScan: false); - this.WriteStartOfScan(frameConfig.Components); + this.WriteStartOfScan(frameConfig.Components, outputStream); encoder.EncodeScanBaselineSingleComponent(frame.Components[0], spectralConverter, cancellationToken); } else if (frame.Interleaved) { frame.AllocateComponents(fullScan: false); - this.WriteStartOfScan(frameConfig.Components); + this.WriteStartOfScan(frameConfig.Components, outputStream); encoder.EncodeScanBaselineInterleaved(frameConfig.EncodingColor, frame, spectralConverter, cancellationToken); } else @@ -613,7 +606,7 @@ private void WriteHuffmanScans(JpegFrame frame, JpegFrameConfig frameCon Span components = frameConfig.Components; for (int i = 0; i < frame.Components.Length; i++) { - this.WriteStartOfScan(components.Slice(i, 1)); + this.WriteStartOfScan(components.Slice(i, 1), outputStream); encoder.EncodeScanBaseline(frame.Components[i], cancellationToken); } } @@ -624,14 +617,14 @@ private void WriteHuffmanScans(JpegFrame frame, JpegFrameConfig frameCon /// /// The marker to write. /// The marker length. - private void WriteMarkerHeader(byte marker, int length) + private void WriteMarkerHeader(byte marker, int length, Stream outputStream) { // Markers are always prefixed with 0xff. this.buffer[0] = JpegConstants.Markers.XFF; this.buffer[1] = marker; this.buffer[2] = (byte)(length >> 8); this.buffer[3] = (byte)(length & 0xff); - this.outputStream.Write(this.buffer, 0, 4); + outputStream.Write(this.buffer, 0, 4); } /// @@ -648,13 +641,13 @@ private void WriteMarkerHeader(byte marker, int length) /// Quantization tables configs. /// Optional quality value from the options. /// Jpeg metadata instance. - private void WriteDefineQuantizationTables(JpegQuantizationTableConfig[] configs, int? optionsQuality, JpegMetadata metadata) + private void WriteDefineQuantizationTables(JpegQuantizationTableConfig[] configs, int? optionsQuality, JpegMetadata metadata, Stream outputStream) { int dataLen = configs.Length * (1 + Block8x8.Size); // Marker + quantization table lengths. int markerlen = 2 + dataLen; - this.WriteMarkerHeader(JpegConstants.Markers.DQT, markerlen); + this.WriteMarkerHeader(JpegConstants.Markers.DQT, markerlen, outputStream); byte[] buffer = new byte[dataLen]; int offset = 0; @@ -684,7 +677,7 @@ private void WriteDefineQuantizationTables(JpegQuantizationTableConfig[] configs } // write filled buffer to the stream - this.outputStream.Write(buffer); + outputStream.Write(buffer); static int GetQualityForTable(int destIndex, int? encoderQuality, JpegMetadata metadata) => destIndex switch { @@ -697,7 +690,7 @@ private void WriteDefineQuantizationTables(JpegQuantizationTableConfig[] configs private JpegFrameConfig GetFrameConfig(JpegMetadata metadata) { JpegEncodingColor color = this.options.ColorType ?? metadata.ColorType ?? JpegEncodingColor.YCbCrRatio420; - JpegFrameConfig frameConfig = Array.Find( + JpegFrameConfig? frameConfig = Array.Find( FrameConfigs, cfg => cfg.EncodingColor == color); diff --git a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs index f2cc631c53..3bf7346ff3 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegImageFormatDetector.cs @@ -12,7 +12,7 @@ public sealed class JpegImageFormatDetector : IImageFormatDetector public int HeaderSize => 11; /// - public IImageFormat DetectFormat(ReadOnlySpan header) + public IImageFormat? DetectFormat(ReadOnlySpan header) => this.IsSupportedFileFormat(header) ? JpegFormat.Instance : null; private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Pbm/BinaryEncoder.cs b/src/ImageSharp/Formats/Pbm/BinaryEncoder.cs index b179c775cf..df6a8d7db6 100644 --- a/src/ImageSharp/Formats/Pbm/BinaryEncoder.cs +++ b/src/ImageSharp/Formats/Pbm/BinaryEncoder.cs @@ -60,7 +60,7 @@ private static void WriteGrayscale(Configuration configuration, Stream s { int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width); Span rowSpan = row.GetSpan(); @@ -85,7 +85,7 @@ private static void WriteWideGrayscale(Configuration configuration, Stre const int bytesPerPixel = 2; int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width * bytesPerPixel); Span rowSpan = row.GetSpan(); @@ -110,7 +110,7 @@ private static void WriteRgb(Configuration configuration, Stream stream, const int bytesPerPixel = 3; int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width * bytesPerPixel); Span rowSpan = row.GetSpan(); @@ -135,7 +135,7 @@ private static void WriteWideRgb(Configuration configuration, Stream str const int bytesPerPixel = 6; int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width * bytesPerPixel); Span rowSpan = row.GetSpan(); @@ -159,7 +159,7 @@ private static void WriteBlackAndWhite(Configuration configuration, Stre { int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width); Span rowSpan = row.GetSpan(); diff --git a/src/ImageSharp/Formats/Pbm/PbmDecoder.cs b/src/ImageSharp/Formats/Pbm/PbmDecoder.cs index 2caf8ecc1f..85d7b57958 100644 --- a/src/ImageSharp/Formats/Pbm/PbmDecoder.cs +++ b/src/ImageSharp/Formats/Pbm/PbmDecoder.cs @@ -44,6 +44,8 @@ Image IImageDecoder.Decode(DecoderOptions options, Stream stream PbmDecoderCore decoder = new(options); Image image = decoder.Decode(options.Configuration, stream, cancellationToken); + ArgumentNullException.ThrowIfNull(image); + ImageDecoderUtilities.Resize(options, image); return image; diff --git a/src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs b/src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs index d5ea66482e..77cae0dd4f 100644 --- a/src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs +++ b/src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; @@ -44,7 +45,7 @@ internal sealed class PbmDecoderCore : IImageDecoderInternals /// /// The decoded by this decoder instance. /// - private ImageMetadata metadata; + private ImageMetadata? metadata; /// /// Initializes a new instance of the class. @@ -60,7 +61,7 @@ public PbmDecoderCore(DecoderOptions options) public DecoderOptions Options { get; } /// - public Size Dimensions => this.pixelSize; + public Size? Dimensions => this.pixelSize; /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) @@ -95,6 +96,7 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella /// Processes the ppm header. /// /// The input stream. + [MemberNotNull(nameof(metadata))] private void ProcessHeader(BufferedReadStream stream) { Span buffer = stackalloc byte[2]; diff --git a/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs b/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs index c982042e02..021cff2670 100644 --- a/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Pbm/PbmImageFormatDetector.cs @@ -16,7 +16,7 @@ public sealed class PbmImageFormatDetector : IImageFormatDetector public int HeaderSize => 2; /// - public IImageFormat DetectFormat(ReadOnlySpan header) => IsSupportedFileFormat(header) ? PbmFormat.Instance : null; + public IImageFormat? DetectFormat(ReadOnlySpan header) => IsSupportedFileFormat(header) ? PbmFormat.Instance : null; private static bool IsSupportedFileFormat(ReadOnlySpan header) { diff --git a/src/ImageSharp/Formats/Pbm/PlainEncoder.cs b/src/ImageSharp/Formats/Pbm/PlainEncoder.cs index 29260f54aa..a6190592a3 100644 --- a/src/ImageSharp/Formats/Pbm/PlainEncoder.cs +++ b/src/ImageSharp/Formats/Pbm/PlainEncoder.cs @@ -74,7 +74,7 @@ private static void WriteGrayscale(Configuration configuration, Stream s { int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width); Span rowSpan = row.GetSpan(); @@ -107,7 +107,7 @@ private static void WriteWideGrayscale(Configuration configuration, Stre { int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width); Span rowSpan = row.GetSpan(); @@ -140,7 +140,7 @@ private static void WriteRgb(Configuration configuration, Stream stream, { int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width); Span rowSpan = row.GetSpan(); @@ -179,7 +179,7 @@ private static void WriteWideRgb(Configuration configuration, Stream str { int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width); Span rowSpan = row.GetSpan(); @@ -218,7 +218,7 @@ private static void WriteBlackAndWhite(Configuration configuration, Stre { int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.PixelBuffer; + Buffer2D pixelBuffer = image.PixelBuffer!; MemoryAllocator allocator = configuration.MemoryAllocator; using IMemoryOwner row = allocator.Allocate(width); Span rowSpan = row.GetSpan(); diff --git a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs index 27d86f9218..1bed8937bf 100644 --- a/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs +++ b/src/ImageSharp/Formats/Png/IPngEncoderOptions.cs @@ -46,7 +46,7 @@ internal interface IPngEncoderOptions /// /// Gets the quantizer for reducing the color count. /// - IQuantizer Quantizer { get; } + IQuantizer? Quantizer { get; } /// /// Gets the transparency threshold. diff --git a/src/ImageSharp/Formats/Png/PngChunk.cs b/src/ImageSharp/Formats/Png/PngChunk.cs index 945661aa57..8fda6454b6 100644 --- a/src/ImageSharp/Formats/Png/PngChunk.cs +++ b/src/ImageSharp/Formats/Png/PngChunk.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Formats.Png; /// internal readonly struct PngChunk { - public PngChunk(int length, PngChunkType type, IMemoryOwner data = null) + public PngChunk(int length, PngChunkType type, IMemoryOwner? data = null) { this.Length = length; this.Type = type; @@ -35,7 +35,7 @@ public PngChunk(int length, PngChunkType type, IMemoryOwner data = null) /// Gets the data bytes appropriate to the chunk type, if any. /// This field can be of zero length or null. /// - public IMemoryOwner Data { get; } + public IMemoryOwner? Data { get; } /// /// Gets a value indicating whether the given chunk is critical to decoding diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index 2247cd6b7b..55515e994d 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO.Compression; using System.Runtime.CompilerServices; @@ -52,11 +53,6 @@ internal sealed class PngDecoderCore : IImageDecoderInternals /// private readonly MemoryAllocator memoryAllocator; - /// - /// The stream to decode from. - /// - private BufferedReadStream currentStream; - /// /// The png header. /// @@ -80,22 +76,22 @@ internal sealed class PngDecoderCore : IImageDecoderInternals /// /// The palette containing color information for indexed png's. /// - private byte[] palette; + private byte[]? palette; /// /// The palette containing alpha channel color information for indexed png's. /// - private byte[] paletteAlpha; + private byte[]? paletteAlpha; /// /// Previous scanline processed. /// - private IMemoryOwner previousScanline; + private IMemoryOwner? previousScanline; /// /// The current scanline that is being processed. /// - private IMemoryOwner scanline; + private IMemoryOwner? scanline; /// /// The index of the current scanline being processed. @@ -142,7 +138,7 @@ internal PngDecoderCore(DecoderOptions options, bool colorMetadataOnly) public DecoderOptions Options { get; } /// - public Size Dimensions => new(this.header.Width, this.header.Height); + public Size? Dimensions => new(this.header.Width, this.header.Height); /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) @@ -150,25 +146,24 @@ public Image Decode(BufferedReadStream stream, CancellationToken { ImageMetadata metadata = new(); PngMetadata pngMetadata = metadata.GetPngMetadata(); - this.currentStream = stream; - this.currentStream.Skip(8); - Image image = null; + stream.Skip(8); + Image? image = null; try { - while (this.TryReadChunk(out PngChunk chunk)) + while (this.TryReadChunk(stream, out PngChunk chunk)) { try { switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan()); + this.ReadHeaderChunk(pngMetadata, chunk.Data!.GetSpan()); break; case PngChunkType.Physical: - ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); + ReadPhysicalChunk(metadata, chunk.Data!.GetSpan()); break; case PngChunkType.Gamma: - ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); + ReadGammaChunk(pngMetadata, chunk.Data!.GetSpan()); break; case PngChunkType.Data: if (image is null) @@ -176,40 +171,40 @@ public Image Decode(BufferedReadStream stream, CancellationToken this.InitializeImage(metadata, out image); } - this.ReadScanlines(chunk, image.Frames.RootFrame, pngMetadata); + this.ReadScanlines(stream, chunk, image.Frames.RootFrame, pngMetadata); break; case PngChunkType.Palette: byte[] pal = new byte[chunk.Length]; - chunk.Data.GetSpan().CopyTo(pal); + chunk.Data!.GetSpan().CopyTo(pal); this.palette = pal; break; case PngChunkType.Transparency: byte[] alpha = new byte[chunk.Length]; - chunk.Data.GetSpan().CopyTo(alpha); + chunk.Data!.GetSpan().CopyTo(alpha); this.paletteAlpha = alpha; this.AssignTransparentMarkers(alpha, pngMetadata); break; case PngChunkType.Text: - this.ReadTextChunk(metadata, pngMetadata, chunk.Data.GetSpan()); + this.ReadTextChunk(metadata, pngMetadata, chunk.Data!.GetSpan()); break; case PngChunkType.CompressedText: - this.ReadCompressedTextChunk(metadata, pngMetadata, chunk.Data.GetSpan()); + this.ReadCompressedTextChunk(metadata, pngMetadata, chunk.Data!.GetSpan()); break; case PngChunkType.InternationalText: - this.ReadInternationalTextChunk(metadata, chunk.Data.GetSpan()); + this.ReadInternationalTextChunk(metadata, chunk.Data!.GetSpan()); break; case PngChunkType.Exif: if (!this.skipMetadata) { byte[] exifData = new byte[chunk.Length]; - chunk.Data.GetSpan().CopyTo(exifData); + chunk.Data!.GetSpan().CopyTo(exifData); MergeOrSetExifProfile(metadata, new ExifProfile(exifData), replaceExistingKeys: true); } break; case PngChunkType.EmbeddedColorProfile: - this.ReadColorProfileChunk(metadata, chunk.Data.GetSpan()); + this.ReadColorProfileChunk(metadata, chunk.Data!.GetSpan()); break; case PngChunkType.End: goto EOF; @@ -250,36 +245,35 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella { ImageMetadata metadata = new(); PngMetadata pngMetadata = metadata.GetPngMetadata(); - this.currentStream = stream; - this.currentStream.Skip(8); + stream.Skip(8); try { - while (this.TryReadChunk(out PngChunk chunk)) + while (this.TryReadChunk(stream, out PngChunk chunk)) { try { switch (chunk.Type) { case PngChunkType.Header: - this.ReadHeaderChunk(pngMetadata, chunk.Data.GetSpan()); + this.ReadHeaderChunk(pngMetadata, chunk.Data!.GetSpan()); break; case PngChunkType.Physical: if (this.colorMetadataOnly) { - this.SkipChunkDataAndCrc(chunk); + this.SkipChunkDataAndCrc(stream, chunk); break; } - ReadPhysicalChunk(metadata, chunk.Data.GetSpan()); + ReadPhysicalChunk(metadata, chunk.Data!.GetSpan()); break; case PngChunkType.Gamma: if (this.colorMetadataOnly) { - this.SkipChunkDataAndCrc(chunk); + this.SkipChunkDataAndCrc(stream, chunk); break; } - ReadGammaChunk(pngMetadata, chunk.Data.GetSpan()); + ReadGammaChunk(pngMetadata, chunk.Data!.GetSpan()); break; case PngChunkType.Data: @@ -289,11 +283,11 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella goto EOF; } - this.SkipChunkDataAndCrc(chunk); + this.SkipChunkDataAndCrc(stream, chunk); break; case PngChunkType.Transparency: byte[] alpha = new byte[chunk.Length]; - chunk.Data.GetSpan().CopyTo(alpha); + chunk.Data!.GetSpan().CopyTo(alpha); this.paletteAlpha = alpha; this.AssignTransparentMarkers(alpha, pngMetadata); @@ -306,41 +300,41 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella case PngChunkType.Text: if (this.colorMetadataOnly) { - this.SkipChunkDataAndCrc(chunk); + this.SkipChunkDataAndCrc(stream, chunk); break; } - this.ReadTextChunk(metadata, pngMetadata, chunk.Data.GetSpan()); + this.ReadTextChunk(metadata, pngMetadata, chunk.Data!.GetSpan()); break; case PngChunkType.CompressedText: if (this.colorMetadataOnly) { - this.SkipChunkDataAndCrc(chunk); + this.SkipChunkDataAndCrc(stream, chunk); break; } - this.ReadCompressedTextChunk(metadata, pngMetadata, chunk.Data.GetSpan()); + this.ReadCompressedTextChunk(metadata, pngMetadata, chunk.Data!.GetSpan()); break; case PngChunkType.InternationalText: if (this.colorMetadataOnly) { - this.SkipChunkDataAndCrc(chunk); + this.SkipChunkDataAndCrc(stream, chunk); break; } - this.ReadInternationalTextChunk(metadata, chunk.Data.GetSpan()); + this.ReadInternationalTextChunk(metadata, chunk.Data!.GetSpan()); break; case PngChunkType.Exif: if (this.colorMetadataOnly) { - this.SkipChunkDataAndCrc(chunk); + this.SkipChunkDataAndCrc(stream, chunk); break; } if (!this.skipMetadata) { byte[] exifData = new byte[chunk.Length]; - chunk.Data.GetSpan().CopyTo(exifData); + chunk.Data!.GetSpan().CopyTo(exifData); MergeOrSetExifProfile(metadata, new ExifProfile(exifData), replaceExistingKeys: true); } @@ -351,7 +345,7 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella default: if (this.colorMetadataOnly) { - this.SkipChunkDataAndCrc(chunk); + this.SkipChunkDataAndCrc(stream, chunk); } break; @@ -397,7 +391,7 @@ private static byte ReadByteLittleEndian(ReadOnlySpan buffer, int offset) /// The number of bits per value. /// The new array. /// The resulting array. - private bool TryScaleUpTo8BitArray(ReadOnlySpan source, int bytesPerScanline, int bits, out IMemoryOwner buffer) + private bool TryScaleUpTo8BitArray(ReadOnlySpan source, int bytesPerScanline, int bits, out IMemoryOwner? buffer) { if (bits >= 8) { @@ -555,12 +549,14 @@ private int CalculateScanlineLength(int width) /// The png chunk containing the compressed scanline data. /// The pixel data. /// The png metadata - private void ReadScanlines(PngChunk chunk, ImageFrame image, PngMetadata pngMetadata) + private void ReadScanlines(BufferedReadStream stream, PngChunk chunk, ImageFrame image, PngMetadata pngMetadata) where TPixel : unmanaged, IPixel { - using ZlibInflateStream deframeStream = new(this.currentStream, this.ReadNextDataChunk); + using ZlibInflateStream deframeStream = new(stream, () => this.ReadNextDataChunk(stream)); deframeStream.AllocateNewBytes(chunk.Length, true); - DeflateStream dataStream = deframeStream.CompressedStream; + DeflateStream? dataStream = deframeStream.CompressedStream; + + ArgumentNullException.ThrowIfNull(dataStream); if (this.header.InterlaceMethod == PngInterlaceMode.Adam7) { @@ -584,6 +580,8 @@ private void DecodePixelData(DeflateStream compressedStream, ImageFrame< { while (this.currentRow < this.header.Height) { + ArgumentNullException.ThrowIfNull(this.scanline); + Span scanlineSpan = this.scanline.GetSpan(); while (this.currentRowBytesRead < this.bytesPerScanline) { @@ -608,14 +606,17 @@ private void DecodePixelData(DeflateStream compressedStream, ImageFrame< break; case FilterType.Up: + ArgumentNullException.ThrowIfNull(this.previousScanline); UpFilter.Decode(scanlineSpan, this.previousScanline.GetSpan()); break; case FilterType.Average: + ArgumentNullException.ThrowIfNull(this.previousScanline); AverageFilter.Decode(scanlineSpan, this.previousScanline.GetSpan(), this.bytesPerPixel); break; case FilterType.Paeth: + ArgumentNullException.ThrowIfNull(this.previousScanline); PaethFilter.Decode(scanlineSpan, this.previousScanline.GetSpan(), this.bytesPerPixel); break; @@ -644,7 +645,7 @@ private void DecodeInterlacedPixelData(DeflateStream compressedStream, I { int pass = 0; int width = this.header.Width; - Buffer2D imageBuffer = image.PixelBuffer; + Buffer2D imageBuffer = image.PixelBuffer!; while (true) { int numColumns = Adam7.ComputeColumns(width, pass); @@ -663,6 +664,7 @@ private void DecodeInterlacedPixelData(DeflateStream compressedStream, I { while (this.currentRowBytesRead < bytesPerInterlaceScanline) { + ArgumentNullException.ThrowIfNull(this.scanline); int bytesRead = compressedStream.Read(this.scanline.GetSpan(), this.currentRowBytesRead, bytesPerInterlaceScanline - this.currentRowBytesRead); if (bytesRead <= 0) { @@ -674,6 +676,9 @@ private void DecodeInterlacedPixelData(DeflateStream compressedStream, I this.currentRowBytesRead = 0; + ArgumentNullException.ThrowIfNull(this.scanline); + ArgumentNullException.ThrowIfNull(this.previousScanline); + Span scanSpan = this.scanline.Slice(0, bytesPerInterlaceScanline); Span prevSpan = this.previousScanline.Slice(0, bytesPerInterlaceScanline); @@ -712,6 +717,7 @@ private void DecodeInterlacedPixelData(DeflateStream compressedStream, I } pass++; + ArgumentNullException.ThrowIfNull(this.previousScanline); this.previousScanline.Clear(); if (pass < 7) @@ -736,13 +742,13 @@ private void DecodeInterlacedPixelData(DeflateStream compressedStream, I private void ProcessDefilteredScanline(ReadOnlySpan defilteredScanline, ImageFrame pixels, PngMetadata pngMetadata) where TPixel : unmanaged, IPixel { - Span rowSpan = pixels.PixelBuffer.DangerousGetRowSpan(this.currentRow); + Span rowSpan = pixels.PixelBuffer!.DangerousGetRowSpan(this.currentRow); // Trim the first marker byte from the buffer ReadOnlySpan trimmed = defilteredScanline[1..]; // Convert 1, 2, and 4 bit pixel data into the 8 bit equivalent. - IMemoryOwner buffer = null; + IMemoryOwner? buffer = null; try { ReadOnlySpan scanlineSpan = this.TryScaleUpTo8BitArray( @@ -750,7 +756,7 @@ private void ProcessDefilteredScanline(ReadOnlySpan defilteredScan this.bytesPerScanline - 1, this.header.BitDepth, out buffer) - ? buffer.GetSpan() + ? buffer!.GetSpan() : trimmed; switch (this.pngColorType) @@ -834,7 +840,7 @@ private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defi ReadOnlySpan trimmed = defilteredScanline[1..]; // Convert 1, 2, and 4 bit pixel data into the 8 bit equivalent. - IMemoryOwner buffer = null; + IMemoryOwner? buffer = null; try { ReadOnlySpan scanlineSpan = this.TryScaleUpTo8BitArray( @@ -842,7 +848,7 @@ private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defi this.bytesPerScanline, this.header.BitDepth, out buffer) - ? buffer.GetSpan() + ? buffer!.GetSpan() : trimmed; switch (this.pngColorType) @@ -1056,7 +1062,7 @@ private void ReadCompressedTextChunk(ImageMetadata baseMetadata, PngMetadata met ReadOnlySpan compressedData = data[(zeroIndex + 2)..]; - if (this.TryUncompressTextData(compressedData, PngConstants.Encoding, out string uncompressed) + if (this.TryUncompressTextData(compressedData, PngConstants.Encoding, out string? uncompressed) && !TryReadTextChunkMetadata(baseMetadata, name, uncompressed)) { metadata.TextData.Add(new PngTextData(name, uncompressed, string.Empty, string.Empty)); @@ -1072,7 +1078,7 @@ private void ReadCompressedTextChunk(ImageMetadata baseMetadata, PngMetadata met /// True if metadata was successfully parsed from the text chunk. False if the /// text chunk was not identified as metadata, and should be stored in the metadata /// object unmodified. - private static bool TryReadTextChunkMetadata(ImageMetadata baseMetadata, string chunkName, string chunkText) + private static bool TryReadTextChunkMetadata(ImageMetadata baseMetadata, string chunkName, string? chunkText) { if (chunkName.Equals("Raw profile type exif", StringComparison.OrdinalIgnoreCase) && TryReadLegacyExifTextChunk(baseMetadata, chunkText)) @@ -1094,7 +1100,7 @@ private static bool TryReadTextChunkMetadata(ImageMetadata baseMetadata, string /// /// The to store the decoded exif tags into. /// The contents of the "raw profile type exif" text chunk. - private static bool TryReadLegacyExifTextChunk(ImageMetadata metadata, string data) + private static bool TryReadLegacyExifTextChunk(ImageMetadata metadata, string? data) { ReadOnlySpan dataSpan = data.AsSpan(); dataSpan = dataSpan.TrimStart(); @@ -1229,11 +1235,11 @@ private unsafe bool TryUncompressZlibData(ReadOnlySpan compressedData, out return false; } - int bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length); + int bytesRead = inflateStream.CompressedStream!.Read(destUncompressedData, 0, destUncompressedData.Length); while (bytesRead != 0) { memoryStreamOutput.Write(destUncompressedData[..bytesRead]); - bytesRead = inflateStream.CompressedStream.Read(destUncompressedData, 0, destUncompressedData.Length); + bytesRead = inflateStream.CompressedStream!.Read(destUncompressedData, 0, destUncompressedData.Length); } uncompressedBytesArray = memoryStreamOutput.ToArray(); @@ -1349,7 +1355,7 @@ private void ReadInternationalTextChunk(ImageMetadata metadata, ReadOnlySpan compressedData = data[dataStartIdx..]; - if (this.TryUncompressTextData(compressedData, PngConstants.TranslatedEncoding, out string uncompressed)) + if (this.TryUncompressTextData(compressedData, PngConstants.TranslatedEncoding, out string? uncompressed)) { pngMetadata.TextData.Add(new PngTextData(keyword, uncompressed, language, translatedKeyword)); } @@ -1372,7 +1378,7 @@ private void ReadInternationalTextChunk(ImageMetadata metadata, ReadOnlySpanThe string encoding to use. /// The uncompressed value. /// The . - private bool TryUncompressTextData(ReadOnlySpan compressedData, Encoding encoding, out string value) + private bool TryUncompressTextData(ReadOnlySpan compressedData, Encoding encoding, [NotNullWhen(true)]out string? value) { if (this.TryUncompressZlibData(compressedData, out byte[] uncompressedData)) { @@ -1388,16 +1394,16 @@ private bool TryUncompressTextData(ReadOnlySpan compressedData, Encoding e /// Reads the next data chunk. /// /// Count of bytes in the next data chunk, or 0 if there are no more data chunks left. - private int ReadNextDataChunk() + private int ReadNextDataChunk(BufferedReadStream stream) { if (this.nextChunk != null) { return 0; } - this.currentStream.Read(this.buffer, 0, 4); + stream.Read(this.buffer, 0, 4); - if (this.TryReadChunk(out PngChunk chunk)) + if (this.TryReadChunk(stream, out PngChunk chunk)) { if (chunk.Type == PngChunkType.Data) { @@ -1418,7 +1424,7 @@ private int ReadNextDataChunk() /// /// The . /// - private bool TryReadChunk(out PngChunk chunk) + private bool TryReadChunk(BufferedReadStream stream, out PngChunk chunk) { if (this.nextChunk != null) { @@ -1429,7 +1435,7 @@ private bool TryReadChunk(out PngChunk chunk) return true; } - if (!this.TryReadChunkLength(out int length)) + if (!this.TryReadChunkLength(stream, out int length)) { chunk = default; @@ -1437,10 +1443,10 @@ private bool TryReadChunk(out PngChunk chunk) return false; } - while (length < 0 || length > (this.currentStream.Length - this.currentStream.Position)) + while (length < 0 || length > (stream.Length - stream.Position)) { // Not a valid chunk so try again until we reach a known chunk. - if (!this.TryReadChunkLength(out length)) + if (!this.TryReadChunkLength(stream, out length)) { chunk = default; @@ -1448,7 +1454,7 @@ private bool TryReadChunk(out PngChunk chunk) } } - PngChunkType type = this.ReadChunkType(); + PngChunkType type = this.ReadChunkType(stream); // If we're reading color metadata only we're only interested in the IHDR and tRNS chunks. // We can skip all other chunk data in the stream for better performance. @@ -1459,19 +1465,19 @@ private bool TryReadChunk(out PngChunk chunk) return true; } - long pos = this.currentStream.Position; + long pos = stream.Position; chunk = new PngChunk( length: length, type: type, - data: this.ReadChunkData(length)); + data: this.ReadChunkData(stream, length)); - this.ValidateChunk(chunk); + this.ValidateChunk(stream, chunk); // Restore the stream position for IDAT chunks, because it will be decoded later and // was only read to verifying the CRC is correct. if (type == PngChunkType.Data) { - this.currentStream.Position = pos; + stream.Position = pos; } return true; @@ -1481,9 +1487,9 @@ private bool TryReadChunk(out PngChunk chunk) /// Validates the png chunk. /// /// The . - private void ValidateChunk(in PngChunk chunk) + private void ValidateChunk(BufferedReadStream stream, in PngChunk chunk) { - uint inputCrc = this.ReadChunkCrc(); + uint inputCrc = this.ReadChunkCrc(stream); if (chunk.IsCritical) { @@ -1491,7 +1497,7 @@ private void ValidateChunk(in PngChunk chunk) BinaryPrimitives.WriteUInt32BigEndian(chunkType, (uint)chunk.Type); uint validCrc = Crc32.Calculate(chunkType); - validCrc = Crc32.Calculate(validCrc, chunk.Data.GetSpan()); + validCrc = Crc32.Calculate(validCrc, chunk.Data!.GetSpan()); if (validCrc != inputCrc) { @@ -1508,10 +1514,10 @@ private void ValidateChunk(in PngChunk chunk) /// Reads the cycle redundancy chunk from the data. /// [MethodImpl(InliningOptions.ShortMethod)] - private uint ReadChunkCrc() + private uint ReadChunkCrc(BufferedReadStream stream) { uint crc = 0; - if (this.currentStream.Read(this.buffer, 0, 4) == 4) + if (stream.Read(this.buffer, 0, 4) == 4) { crc = BinaryPrimitives.ReadUInt32BigEndian(this.buffer); } @@ -1524,10 +1530,10 @@ private uint ReadChunkCrc() /// /// The image format chunk. [MethodImpl(InliningOptions.ShortMethod)] - private void SkipChunkDataAndCrc(in PngChunk chunk) + private void SkipChunkDataAndCrc(BufferedReadStream stream, in PngChunk chunk) { - this.currentStream.Skip(chunk.Length); - this.currentStream.Skip(4); + stream.Skip(chunk.Length); + stream.Skip(4); } /// @@ -1535,12 +1541,12 @@ private void SkipChunkDataAndCrc(in PngChunk chunk) /// /// The length of the chunk data to read. [MethodImpl(InliningOptions.ShortMethod)] - private IMemoryOwner ReadChunkData(int length) + private IMemoryOwner ReadChunkData(BufferedReadStream stream, int length) { // We rent the buffer here to return it afterwards in Decode() IMemoryOwner buffer = this.configuration.MemoryAllocator.Allocate(length, AllocationOptions.Clean); - this.currentStream.Read(buffer.GetSpan(), 0, length); + stream.Read(buffer.GetSpan(), 0, length); return buffer; } @@ -1552,9 +1558,9 @@ private IMemoryOwner ReadChunkData(int length) /// Thrown if the input stream is not valid. /// [MethodImpl(InliningOptions.ShortMethod)] - private PngChunkType ReadChunkType() + private PngChunkType ReadChunkType(BufferedReadStream stream) { - if (this.currentStream.Read(this.buffer, 0, 4) == 4) + if (stream.Read(this.buffer, 0, 4) == 4) { return (PngChunkType)BinaryPrimitives.ReadUInt32BigEndian(this.buffer); } @@ -1573,9 +1579,9 @@ private PngChunkType ReadChunkType() /// Whether the length was read. /// [MethodImpl(InliningOptions.ShortMethod)] - private bool TryReadChunkLength(out int result) + private bool TryReadChunkLength(BufferedReadStream stream, out int result) { - if (this.currentStream.Read(this.buffer, 0, 4) == 4) + if (stream.Read(this.buffer, 0, 4) == 4) { result = BinaryPrimitives.ReadInt32BigEndian(this.buffer); diff --git a/src/ImageSharp/Formats/Png/PngEncoder.cs b/src/ImageSharp/Formats/Png/PngEncoder.cs index d769bcbc8d..7856366677 100644 --- a/src/ImageSharp/Formats/Png/PngEncoder.cs +++ b/src/ImageSharp/Formats/Png/PngEncoder.cs @@ -31,7 +31,7 @@ public sealed class PngEncoder : IImageEncoder, IPngEncoderOptions public float? Gamma { get; set; } /// - public IQuantizer Quantizer { get; set; } + public IQuantizer? Quantizer { get; set; } /// public byte Threshold { get; set; } = byte.MaxValue; diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index c45da6a825..9854c4c5a4 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Common.Helpers; @@ -78,12 +79,12 @@ internal sealed class PngEncoderCore : IImageEncoderInternals, IDisposable /// /// The raw data of previous scanline. /// - private IMemoryOwner previousScanline; + private IMemoryOwner? previousScanline; /// /// The raw data of current scanline. /// - private IMemoryOwner currentScanline; + private IMemoryOwner? currentScanline; /// /// The color profile name. @@ -123,7 +124,7 @@ public void Encode(Image image, Stream stream, CancellationToken PngMetadata pngMetadata = metadata.GetFormatMetadata(PngFormat.Instance); PngEncoderOptionsHelpers.AdjustOptions(this.options, pngMetadata, out this.use16Bit, out this.bytesPerPixel); - Image clonedImage = null; + Image? clonedImage = null; bool clearTransparency = this.options.TransparentColorMode == PngTransparentColorMode.Clear; if (clearTransparency) { @@ -131,7 +132,7 @@ public void Encode(Image image, Stream stream, CancellationToken ClearTransparentPixels(clonedImage); } - IndexedImageFrame quantized = this.CreateQuantizedImage(image, clonedImage); + IndexedImageFrame? quantized = this.CreateQuantizedImage(image, clonedImage!); stream.Write(PngConstants.HeaderBytes); @@ -144,7 +145,7 @@ public void Encode(Image image, Stream stream, CancellationToken this.WriteExifChunk(stream, metadata); this.WriteXmpChunk(stream, metadata); this.WriteTextChunks(stream, pngMetadata); - this.WriteDataChunks(clearTransparency ? clonedImage : image, quantized, stream); + this.WriteDataChunks(clearTransparency ? clonedImage! : image, quantized, stream); this.WriteEndChunk(stream); stream.Flush(); @@ -158,8 +159,6 @@ public void Dispose() { this.previousScanline?.Dispose(); this.currentScanline?.Dispose(); - this.previousScanline = null; - this.currentScanline = null; } /// @@ -195,10 +194,10 @@ private static void ClearTransparentPixels(Image image) /// The image to quantize. /// Cloned image with transparent pixels are changed to black. /// The quantized image. - private IndexedImageFrame CreateQuantizedImage(Image image, Image clonedImage) + private IndexedImageFrame? CreateQuantizedImage(Image image, Image clonedImage) where TPixel : unmanaged, IPixel { - IndexedImageFrame quantized; + IndexedImageFrame? quantized; if (this.options.TransparentColorMode == PngTransparentColorMode.Clear) { quantized = PngEncoderOptionsHelpers.CreateQuantizedFrame(this.options, clonedImage); @@ -220,6 +219,8 @@ private void CollectGrayscaleBytes(ReadOnlySpan rowSpan) where TPixel : unmanaged, IPixel { ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan); + ArgumentNullException.ThrowIfNull(this.currentScanline); + Span rawScanlineSpan = this.currentScanline.GetSpan(); ref byte rawScanlineSpanRef = ref MemoryMarshal.GetReference(rawScanlineSpan); @@ -302,6 +303,7 @@ private void CollectGrayscaleBytes(ReadOnlySpan rowSpan) private void CollectTPixelBytes(ReadOnlySpan rowSpan) where TPixel : unmanaged, IPixel { + ArgumentNullException.ThrowIfNull(this.currentScanline); Span rawScanlineSpan = this.currentScanline.GetSpan(); switch (this.bytesPerPixel) @@ -379,20 +381,22 @@ private void CollectTPixelBytes(ReadOnlySpan rowSpan) /// The row span. /// The quantized pixels. Can be null. /// The row. - private void CollectPixelBytes(ReadOnlySpan rowSpan, IndexedImageFrame quantized, int row) + private void CollectPixelBytes(ReadOnlySpan rowSpan, IndexedImageFrame? quantized, int row) where TPixel : unmanaged, IPixel { switch (this.options.ColorType) { case PngColorType.Palette: + ArgumentNullException.ThrowIfNull(this.currentScanline); + if (this.bitDepth < 8) { - PngEncoderHelpers.ScaleDownFrom8BitArray(quantized.DangerousGetRowSpan(row), this.currentScanline.GetSpan(), this.bitDepth); + PngEncoderHelpers.ScaleDownFrom8BitArray(quantized!.DangerousGetRowSpan(row), this.currentScanline.GetSpan(), this.bitDepth); } else { - quantized.DangerousGetRowSpan(row).CopyTo(this.currentScanline.GetSpan()); + quantized?.DangerousGetRowSpan(row).CopyTo(this.currentScanline.GetSpan()); } break; @@ -413,6 +417,9 @@ private void CollectPixelBytes(ReadOnlySpan rowSpan, IndexedImag /// Used for attempting optimized filtering. private void FilterPixelBytes(ref Span filter, ref Span attempt) { + ArgumentNullException.ThrowIfNull(this.previousScanline); + ArgumentNullException.ThrowIfNull(this.currentScanline); + switch (this.options.FilterMethod) { case PngFilterMethod.None: @@ -453,7 +460,7 @@ private void CollectAndFilterPixelRow( ReadOnlySpan rowSpan, ref Span filter, ref Span attempt, - IndexedImageFrame quantized, + IndexedImageFrame? quantized, int row) where TPixel : unmanaged, IPixel { @@ -472,6 +479,8 @@ private void EncodeAdam7IndexedPixelRow( ref Span filter, ref Span attempt) { + ArgumentNullException.ThrowIfNull(this.currentScanline); + // CollectPixelBytes if (this.bitDepth < 8) { @@ -493,6 +502,9 @@ private void EncodeAdam7IndexedPixelRow( /// Used for attempting optimized filtering. private void ApplyOptimalFilteredScanline(ref Span filter, ref Span attempt) { + ArgumentNullException.ThrowIfNull(this.previousScanline); + ArgumentNullException.ThrowIfNull(this.currentScanline); + // Palette images don't compress well with adaptive filtering. // Nor do images comprising a single row. if (this.options.ColorType == PngColorType.Palette || this.height == 1 || this.bitDepth < 8) @@ -543,10 +555,10 @@ private void WriteHeaderChunk(Stream stream) width: this.width, height: this.height, bitDepth: this.bitDepth, - colorType: this.options.ColorType.Value, + colorType: this.options.ColorType!.Value, compressionMethod: 0, // None filterMethod: 0, - interlaceMethod: this.options.InterlaceMethod.Value); + interlaceMethod: this.options.InterlaceMethod!.Value); header.WriteTo(this.chunkDataBuffer); @@ -560,7 +572,7 @@ private void WriteHeaderChunk(Stream stream) /// The pixel format. /// The containing image data. /// The quantized frame. - private void WritePaletteChunk(Stream stream, IndexedImageFrame quantized) + private void WritePaletteChunk(Stream stream, IndexedImageFrame? quantized) where TPixel : unmanaged, IPixel { if (quantized is null) @@ -668,9 +680,9 @@ private void WriteXmpChunk(Stream stream, ImageMetadata meta) return; } - byte[] xmpData = meta.XmpProfile.Data; + byte[]? xmpData = meta.XmpProfile.Data; - if (xmpData.Length == 0) + if (xmpData!.Length == 0) { return; } @@ -916,7 +928,7 @@ private void WriteTransparencyChunk(Stream stream, PngMetadata pngMetadata) /// The image. /// The quantized pixel data. Can be null. /// The stream. - private void WriteDataChunks(Image pixels, IndexedImageFrame quantized, Stream stream) + private void WriteDataChunks(Image pixels, IndexedImageFrame? quantized, Stream stream) where TPixel : unmanaged, IPixel { byte[] buffer; @@ -973,6 +985,8 @@ private void WriteDataChunks(Image pixels, IndexedImageFrame /// The bytes per scanline. + [MemberNotNull(nameof(currentScanline))] + [MemberNotNull(nameof(previousScanline))] private void AllocateScanlineBuffers(int bytesPerScanline) { // Clean up from any potential previous runs. @@ -989,7 +1003,7 @@ private void AllocateScanlineBuffers(int bytesPerScanline) /// The pixels. /// The quantized pixels span. /// The deflate stream. - private void EncodePixels(Image pixels, IndexedImageFrame quantized, ZlibDeflateStream deflateStream) + private void EncodePixels(Image pixels, IndexedImageFrame? quantized, ZlibDeflateStream deflateStream) where TPixel : unmanaged, IPixel { int bytesPerScanline = this.CalculateScanlineLength(this.width); @@ -1023,7 +1037,7 @@ private void EncodeAdam7Pixels(Image image, ZlibDeflateStream de { int width = image.Width; int height = image.Height; - Buffer2D pixelBuffer = image.Frames.RootFrame.PixelBuffer; + Buffer2D pixelBuffer = image.Frames.RootFrame.PixelBuffer!; for (int pass = 0; pass < 7; pass++) { int startRow = Adam7.FirstRow[pass]; @@ -1188,8 +1202,11 @@ private int CalculateScanlineLength(int width) [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SwapScanlineBuffers() { - ref IMemoryOwner prev = ref this.previousScanline; - ref IMemoryOwner current = ref this.currentScanline; + ArgumentNullException.ThrowIfNull(this.previousScanline); + ArgumentNullException.ThrowIfNull(this.currentScanline); + + ref IMemoryOwner? prev = ref this.previousScanline; + ref IMemoryOwner? current = ref this.currentScanline; RuntimeUtility.Swap(ref prev, ref current); } } diff --git a/src/ImageSharp/Formats/Png/PngEncoderOptions.cs b/src/ImageSharp/Formats/Png/PngEncoderOptions.cs index 7fe27b78d7..c58fc65767 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderOptions.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderOptions.cs @@ -49,7 +49,7 @@ public PngEncoderOptions(IPngEncoderOptions source) public float? Gamma { get; set; } /// - public IQuantizer Quantizer { get; set; } + public IQuantizer? Quantizer { get; set; } /// public byte Threshold { get; } diff --git a/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs b/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs index e1ee61c378..65b9dedae2 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs @@ -72,7 +72,7 @@ public static void AdjustOptions( /// The type of the pixel. /// The options. /// The image. - public static IndexedImageFrame CreateQuantizedFrame( + public static IndexedImageFrame? CreateQuantizedFrame( PngEncoderOptions options, Image image) where TPixel : unmanaged, IPixel @@ -85,7 +85,7 @@ public static IndexedImageFrame CreateQuantizedFrame( // Use the metadata to determine what quantization depth to use if no quantizer has been set. if (options.Quantizer is null) { - byte bits = (byte)options.BitDepth; + byte bits = (byte)options.BitDepth!; var maxColors = ColorNumerics.GetColorCountForBitDepth(bits); options.Quantizer = new WuQuantizer(new QuantizerOptions { MaxColors = maxColors }); } @@ -106,14 +106,14 @@ public static IndexedImageFrame CreateQuantizedFrame( /// The quantized frame. public static byte CalculateBitDepth( PngEncoderOptions options, - IndexedImageFrame quantizedFrame) + IndexedImageFrame? quantizedFrame) where TPixel : unmanaged, IPixel { byte bitDepth; if (options.ColorType == PngColorType.Palette) { - byte quantizedBits = (byte)Numerics.Clamp(ColorNumerics.GetBitsNeededForColorDepth(quantizedFrame.Palette.Length), 1, 8); - byte bits = Math.Max((byte)options.BitDepth, quantizedBits); + byte quantizedBits = (byte)Numerics.Clamp(ColorNumerics.GetBitsNeededForColorDepth(quantizedFrame!.Palette.Length), 1, 8); + byte bits = Math.Max((byte)options.BitDepth!, quantizedBits); // Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk // We check again for the bit depth as the bit depth of the color palette from a given quantizer might not @@ -131,10 +131,10 @@ public static byte CalculateBitDepth( } else { - bitDepth = (byte)options.BitDepth; + bitDepth = (byte)options.BitDepth!; } - if (Array.IndexOf(PngConstants.ColorTypes[options.ColorType.Value], bitDepth) == -1) + if (Array.IndexOf(PngConstants.ColorTypes[options.ColorType!.Value], bitDepth) == -1) { throw new NotSupportedException("Bit depth is not supported or not valid."); } diff --git a/src/ImageSharp/Formats/Png/PngHeader.cs b/src/ImageSharp/Formats/Png/PngHeader.cs index cee1017f12..559432a99d 100644 --- a/src/ImageSharp/Formats/Png/PngHeader.cs +++ b/src/ImageSharp/Formats/Png/PngHeader.cs @@ -87,7 +87,7 @@ public PngHeader( /// public void Validate() { - if (!PngConstants.ColorTypes.TryGetValue(this.ColorType, out byte[] supportedBitDepths)) + if (!PngConstants.ColorTypes.TryGetValue(this.ColorType, out byte[]? supportedBitDepths)) { throw new NotSupportedException($"Invalid or unsupported color type. Was '{this.ColorType}'."); } diff --git a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs index 907898e17f..2e20668248 100644 --- a/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Png/PngImageFormatDetector.cs @@ -14,7 +14,7 @@ public sealed class PngImageFormatDetector : IImageFormatDetector public int HeaderSize => 8; /// - public IImageFormat DetectFormat(ReadOnlySpan header) + public IImageFormat? DetectFormat(ReadOnlySpan header) { return this.IsSupportedFileFormat(header) ? PngFormat.Instance : null; } diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs index cf77788bc0..af09f4d1af 100644 --- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs +++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs @@ -236,7 +236,7 @@ public static void ProcessPaletteScanline( ReadOnlySpan scanlineSpan, Span rowSpan, ReadOnlySpan palette, - byte[] paletteAlpha) + byte[]? paletteAlpha) where TPixel : unmanaged, IPixel { if (palette.IsEmpty) @@ -287,7 +287,7 @@ public static void ProcessInterlacedPaletteScanline( int pixelOffset, int increment, ReadOnlySpan palette, - byte[] paletteAlpha) + byte[]? paletteAlpha) where TPixel : unmanaged, IPixel { TPixel pixel = default; diff --git a/src/ImageSharp/Formats/Png/PngTextData.cs b/src/ImageSharp/Formats/Png/PngTextData.cs index af2ba4b1db..8ef4f1821d 100644 --- a/src/ImageSharp/Formats/Png/PngTextData.cs +++ b/src/ImageSharp/Formats/Png/PngTextData.cs @@ -98,7 +98,7 @@ public PngTextData(string keyword, string value, string languageTag, string tran /// true if and this instance are the same type and represent the /// same value; otherwise, false. /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is PngTextData other && this.Equals(other); /// diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs index efb61610c2..1bc6a16b02 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; @@ -28,12 +29,12 @@ internal sealed class TgaDecoderCore : IImageDecoderInternals /// /// The metadata. /// - private ImageMetadata metadata; + private ImageMetadata? metadata; /// /// The tga specific metadata. /// - private TgaMetadata tgaMetadata; + private TgaMetadata? tgaMetadata; /// /// The file header containing general information about the image. @@ -45,11 +46,6 @@ internal sealed class TgaDecoderCore : IImageDecoderInternals /// private readonly MemoryAllocator memoryAllocator; - /// - /// The stream to decode from. - /// - private BufferedReadStream currentStream; - /// /// Indicates whether there is a alpha channel present. /// @@ -70,7 +66,7 @@ public TgaDecoderCore(DecoderOptions options) public DecoderOptions Options { get; } /// - public Size Dimensions => new(this.fileHeader.Width, this.fileHeader.Height); + public Size? Dimensions => new(this.fileHeader.Width, this.fileHeader.Height); /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) @@ -79,7 +75,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken try { TgaImageOrigin origin = this.ReadFileHeader(stream); - this.currentStream.Skip(this.fileHeader.IdLength); + stream.Skip(this.fileHeader.IdLength); // Parse the color map, if present. if (this.fileHeader.ColorMapType is not 0 and not 1) @@ -112,7 +108,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken using (IMemoryOwner palette = this.memoryAllocator.Allocate(colorMapSizeInBytes, AllocationOptions.Clean)) { Span paletteSpan = palette.GetSpan(); - int bytesRead = this.currentStream.Read(paletteSpan, this.fileHeader.CMapStart, colorMapSizeInBytes); + int bytesRead = stream.Read(paletteSpan, this.fileHeader.CMapStart, colorMapSizeInBytes); if (bytesRead != colorMapSizeInBytes) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read the color map"); @@ -121,6 +117,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken if (this.fileHeader.ImageType == TgaImageType.RleColorMapped) { this.ReadPalettedRle( + stream, this.fileHeader.Width, this.fileHeader.Height, pixels, @@ -131,6 +128,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken else { this.ReadPaletted( + stream, this.fileHeader.Width, this.fileHeader.Height, pixels, @@ -147,7 +145,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken if (this.fileHeader.CMapLength > 0) { int colorMapPixelSizeInBytes = this.fileHeader.CMapDepth / 8; - this.currentStream.Skip(this.fileHeader.CMapLength * colorMapPixelSizeInBytes); + stream.Skip(this.fileHeader.CMapLength * colorMapPixelSizeInBytes); } switch (this.fileHeader.PixelDepth) @@ -155,11 +153,11 @@ public Image Decode(BufferedReadStream stream, CancellationToken case 8: if (this.fileHeader.ImageType.IsRunLengthEncoded()) { - this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 1, origin); + this.ReadRle(stream, this.fileHeader.Width, this.fileHeader.Height, this.tgaMetadata.AlphaChannelBits, pixels, 1, origin); } else { - this.ReadMonoChrome(this.fileHeader.Width, this.fileHeader.Height, pixels, origin); + this.ReadMonoChrome(stream, this.fileHeader.Width, this.fileHeader.Height, pixels, origin); } break; @@ -168,11 +166,11 @@ public Image Decode(BufferedReadStream stream, CancellationToken case 16: if (this.fileHeader.ImageType.IsRunLengthEncoded()) { - this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 2, origin); + this.ReadRle(stream, this.fileHeader.Width, this.fileHeader.Height, this.tgaMetadata.AlphaChannelBits, pixels, 2, origin); } else { - this.ReadBgra16(this.fileHeader.Width, this.fileHeader.Height, pixels, origin); + this.ReadBgra16(this.fileHeader.Width, this.fileHeader.Height, stream, pixels, origin); } break; @@ -180,11 +178,11 @@ public Image Decode(BufferedReadStream stream, CancellationToken case 24: if (this.fileHeader.ImageType.IsRunLengthEncoded()) { - this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 3, origin); + this.ReadRle(stream, this.fileHeader.Width, this.fileHeader.Height, this.tgaMetadata.AlphaChannelBits, pixels, 3, origin); } else { - this.ReadBgr24(this.fileHeader.Width, this.fileHeader.Height, pixels, origin); + this.ReadBgr24(stream, this.fileHeader.Width, this.fileHeader.Height, pixels, origin); } break; @@ -192,11 +190,11 @@ public Image Decode(BufferedReadStream stream, CancellationToken case 32: if (this.fileHeader.ImageType.IsRunLengthEncoded()) { - this.ReadRle(this.fileHeader.Width, this.fileHeader.Height, pixels, 4, origin); + this.ReadRle(stream, this.fileHeader.Width, this.fileHeader.Height, this.tgaMetadata.AlphaChannelBits, pixels, 4, origin); } else { - this.ReadBgra32(this.fileHeader.Width, this.fileHeader.Height, pixels, origin); + this.ReadBgra32(stream, this.fileHeader.Width, this.fileHeader.Height, this.tgaMetadata.AlphaChannelBits, pixels, origin); } break; @@ -224,7 +222,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken /// The color palette. /// Color map size of one entry in bytes. /// The image origin. - private void ReadPaletted(int width, int height, Buffer2D pixels, Span palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin) + private void ReadPaletted(BufferedReadStream stream, int width, int height, Buffer2D pixels, Span palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin) where TPixel : unmanaged, IPixel { TPixel color = default; @@ -242,14 +240,14 @@ private void ReadPaletted(int width, int height, Buffer2D pixels { for (int x = width - 1; x >= 0; x--) { - this.ReadPalettedBgra16Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow); + this.ReadPalettedBgra16Pixel(stream, palette, colorMapPixelSizeInBytes, x, color, pixelRow); } } else { for (int x = 0; x < width; x++) { - this.ReadPalettedBgra16Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow); + this.ReadPalettedBgra16Pixel(stream, palette, colorMapPixelSizeInBytes, x, color, pixelRow); } } @@ -260,14 +258,14 @@ private void ReadPaletted(int width, int height, Buffer2D pixels { for (int x = width - 1; x >= 0; x--) { - this.ReadPalettedBgr24Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow); + this.ReadPalettedBgr24Pixel(stream, palette, colorMapPixelSizeInBytes, x, color, pixelRow); } } else { for (int x = 0; x < width; x++) { - this.ReadPalettedBgr24Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow); + this.ReadPalettedBgr24Pixel(stream, palette, colorMapPixelSizeInBytes, x, color, pixelRow); } } @@ -278,14 +276,14 @@ private void ReadPaletted(int width, int height, Buffer2D pixels { for (int x = width - 1; x >= 0; x--) { - this.ReadPalettedBgra32Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow); + this.ReadPalettedBgra32Pixel(stream, palette, colorMapPixelSizeInBytes, x, color, pixelRow); } } else { for (int x = 0; x < width; x++) { - this.ReadPalettedBgra32Pixel(palette, colorMapPixelSizeInBytes, x, color, pixelRow); + this.ReadPalettedBgra32Pixel(stream, palette, colorMapPixelSizeInBytes, x, color, pixelRow); } } @@ -304,14 +302,14 @@ private void ReadPaletted(int width, int height, Buffer2D pixels /// The color palette. /// Color map size of one entry in bytes. /// The image origin. - private void ReadPalettedRle(int width, int height, Buffer2D pixels, Span palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin) + private void ReadPalettedRle(BufferedReadStream stream, int width, int height, Buffer2D pixels, Span palette, int colorMapPixelSizeInBytes, TgaImageOrigin origin) where TPixel : unmanaged, IPixel { using (IMemoryOwner buffer = this.memoryAllocator.Allocate(width * height, AllocationOptions.Clean)) { TPixel color = default; Span bufferSpan = buffer.GetSpan(); - this.UncompressRle(width, height, bufferSpan, bytesPerPixel: 1); + this.UncompressRle(stream, width, height, bufferSpan, bytesPerPixel: 1); for (int y = 0; y < height; y++) { @@ -352,7 +350,7 @@ private void ReadPalettedRle(int width, int height, Buffer2D pix /// The height of the image. /// The to assign the palette to. /// the image origin. - private void ReadMonoChrome(int width, int height, Buffer2D pixels, TgaImageOrigin origin) + private void ReadMonoChrome(BufferedReadStream stream, int width, int height, Buffer2D pixels, TgaImageOrigin origin) where TPixel : unmanaged, IPixel { bool invertX = InvertX(origin); @@ -365,7 +363,7 @@ private void ReadMonoChrome(int width, int height, Buffer2D pixe Span pixelSpan = pixels.DangerousGetRowSpan(newY); for (int x = width - 1; x >= 0; x--) { - this.ReadL8Pixel(color, x, pixelSpan); + this.ReadL8Pixel(stream, color, x, pixelSpan); } } @@ -379,14 +377,14 @@ private void ReadMonoChrome(int width, int height, Buffer2D pixe { for (int y = height - 1; y >= 0; y--) { - this.ReadL8Row(width, pixels, rowSpan, y); + this.ReadL8Row(width, stream, pixels, rowSpan, y); } } else { for (int y = 0; y < height; y++) { - this.ReadL8Row(width, pixels, rowSpan, y); + this.ReadL8Row(width, stream, pixels, rowSpan, y); } } } @@ -399,7 +397,7 @@ private void ReadMonoChrome(int width, int height, Buffer2D pixe /// The height of the image. /// The to assign the palette to. /// The image origin. - private void ReadBgra16(int width, int height, Buffer2D pixels, TgaImageOrigin origin) + private void ReadBgra16(int width, int height, BufferedReadStream stream, Buffer2D pixels, TgaImageOrigin origin) where TPixel : unmanaged, IPixel { TPixel color = default; @@ -416,7 +414,7 @@ private void ReadBgra16(int width, int height, Buffer2D pixels, { for (int x = width - 1; x >= 0; x--) { - int bytesRead = this.currentStream.Read(this.scratchBuffer, 0, 2); + int bytesRead = stream.Read(this.scratchBuffer, 0, 2); if (bytesRead != 2) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); @@ -441,7 +439,7 @@ private void ReadBgra16(int width, int height, Buffer2D pixels, } else { - int bytesRead = this.currentStream.Read(rowSpan); + int bytesRead = stream.Read(rowSpan); if (bytesRead != rowSpan.Length) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); @@ -476,7 +474,7 @@ private void ReadBgra16(int width, int height, Buffer2D pixels, /// The height of the image. /// The to assign the palette to. /// The image origin. - private void ReadBgr24(int width, int height, Buffer2D pixels, TgaImageOrigin origin) + private void ReadBgr24(BufferedReadStream stream, int width, int height, Buffer2D pixels, TgaImageOrigin origin) where TPixel : unmanaged, IPixel { bool invertX = InvertX(origin); @@ -489,7 +487,7 @@ private void ReadBgr24(int width, int height, Buffer2D pixels, T Span pixelSpan = pixels.DangerousGetRowSpan(newY); for (int x = width - 1; x >= 0; x--) { - this.ReadBgr24Pixel(color, x, pixelSpan); + this.ReadBgr24Pixel(stream, color, x, pixelSpan); } } @@ -504,14 +502,14 @@ private void ReadBgr24(int width, int height, Buffer2D pixels, T { for (int y = height - 1; y >= 0; y--) { - this.ReadBgr24Row(width, pixels, rowSpan, y); + this.ReadBgr24Row(stream, width, pixels, rowSpan, y); } } else { for (int y = 0; y < height; y++) { - this.ReadBgr24Row(width, pixels, rowSpan, y); + this.ReadBgr24Row(stream, width, pixels, rowSpan, y); } } } @@ -524,12 +522,12 @@ private void ReadBgr24(int width, int height, Buffer2D pixels, T /// The height of the image. /// The to assign the palette to. /// The image origin. - private void ReadBgra32(int width, int height, Buffer2D pixels, TgaImageOrigin origin) + private void ReadBgra32(BufferedReadStream stream, int width, int height, byte alphaChannelBits, Buffer2D pixels, TgaImageOrigin origin) where TPixel : unmanaged, IPixel { TPixel color = default; bool invertX = InvertX(origin); - if (this.tgaMetadata.AlphaChannelBits == 8 && !invertX) + if (alphaChannelBits == 8 && !invertX) { using IMemoryOwner row = this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, 4, 0); Span rowSpan = row.GetSpan(); @@ -538,14 +536,14 @@ private void ReadBgra32(int width, int height, Buffer2D pixels, { for (int y = height - 1; y >= 0; y--) { - this.ReadBgra32Row(width, pixels, rowSpan, y); + this.ReadBgra32Row(stream, width, pixels, rowSpan, y); } } else { for (int y = 0; y < height; y++) { - this.ReadBgra32Row(width, pixels, rowSpan, y); + this.ReadBgra32Row(stream, width, pixels, rowSpan, y); } } @@ -560,14 +558,14 @@ private void ReadBgra32(int width, int height, Buffer2D pixels, { for (int x = width - 1; x >= 0; x--) { - this.ReadBgra32Pixel(x, color, pixelRow); + this.ReadBgra32Pixel(stream, x, alphaChannelBits, color, pixelRow); } } else { for (int x = 0; x < width; x++) { - this.ReadBgra32Pixel(x, color, pixelRow); + this.ReadBgra32Pixel(stream, x, alphaChannelBits, color, pixelRow); } } } @@ -582,15 +580,14 @@ private void ReadBgra32(int width, int height, Buffer2D pixels, /// The to assign the palette to. /// The bytes per pixel. /// The image origin. - private void ReadRle(int width, int height, Buffer2D pixels, int bytesPerPixel, TgaImageOrigin origin) + private void ReadRle(BufferedReadStream stream, int width, int height, byte alphaChannelBits, Buffer2D pixels, int bytesPerPixel, TgaImageOrigin origin) where TPixel : unmanaged, IPixel { TPixel color = default; - byte alphaBits = this.tgaMetadata.AlphaChannelBits; using (IMemoryOwner buffer = this.memoryAllocator.Allocate(width * height * bytesPerPixel, AllocationOptions.Clean)) { Span bufferSpan = buffer.GetSpan(); - this.UncompressRle(width, height, bufferSpan, bytesPerPixel); + this.UncompressRle(stream, width, height, bufferSpan, bytesPerPixel); for (int y = 0; y < height; y++) { int newY = InvertY(y, height, origin); @@ -631,7 +628,7 @@ private void ReadRle(int width, int height, Buffer2D pixels, int } else { - byte alpha = alphaBits == 0 ? byte.MaxValue : bufferSpan[idx + 3]; + byte alpha = alphaChannelBits == 0 ? byte.MaxValue : bufferSpan[idx + 3]; color.FromBgra32(new Bgra32(bufferSpan[idx + 2], bufferSpan[idx + 1], bufferSpan[idx], alpha)); } @@ -657,10 +654,10 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadL8Row(int width, Buffer2D pixels, Span row, int y) + private void ReadL8Row(int width, BufferedReadStream stream, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { - int bytesRead = this.currentStream.Read(row); + int bytesRead = stream.Read(row); if (bytesRead != row.Length) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); @@ -671,19 +668,19 @@ private void ReadL8Row(int width, Buffer2D pixels, Span ro } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadL8Pixel(TPixel color, int x, Span pixelSpan) + private void ReadL8Pixel(BufferedReadStream stream, TPixel color, int x, Span pixelSpan) where TPixel : unmanaged, IPixel { - byte pixelValue = (byte)this.currentStream.ReadByte(); + byte pixelValue = (byte)stream.ReadByte(); color.FromL8(Unsafe.As(ref pixelValue)); pixelSpan[x] = color; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadBgr24Pixel(TPixel color, int x, Span pixelSpan) + private void ReadBgr24Pixel(BufferedReadStream stream, TPixel color, int x, Span pixelSpan) where TPixel : unmanaged, IPixel { - int bytesRead = this.currentStream.Read(this.scratchBuffer, 0, 3); + int bytesRead = stream.Read(this.scratchBuffer, 0, 3); if (bytesRead != 3) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a bgr pixel"); @@ -694,10 +691,10 @@ private void ReadBgr24Pixel(TPixel color, int x, Span pixelSpan) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadBgr24Row(int width, Buffer2D pixels, Span row, int y) + private void ReadBgr24Row(BufferedReadStream stream, int width, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { - int bytesRead = this.currentStream.Read(row); + int bytesRead = stream.Read(row); if (bytesRead != row.Length) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); @@ -708,25 +705,25 @@ private void ReadBgr24Row(int width, Buffer2D pixels, Span } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadBgra32Pixel(int x, TPixel color, Span pixelRow) + private void ReadBgra32Pixel(BufferedReadStream stream, int x, byte alphaChannelBits, TPixel color, Span pixelRow) where TPixel : unmanaged, IPixel { - int bytesRead = this.currentStream.Read(this.scratchBuffer, 0, 4); + int bytesRead = stream.Read(this.scratchBuffer, 0, 4); if (bytesRead != 4) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a bgra pixel"); } - byte alpha = this.tgaMetadata.AlphaChannelBits == 0 ? byte.MaxValue : this.scratchBuffer[3]; + byte alpha = alphaChannelBits == 0 ? byte.MaxValue : this.scratchBuffer[3]; color.FromBgra32(new Bgra32(this.scratchBuffer[2], this.scratchBuffer[1], this.scratchBuffer[0], alpha)); pixelRow[x] = color; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadBgra32Row(int width, Buffer2D pixels, Span row, int y) + private void ReadBgra32Row(BufferedReadStream stream, int width, Buffer2D pixels, Span row, int y) where TPixel : unmanaged, IPixel { - int bytesRead = this.currentStream.Read(row); + int bytesRead = stream.Read(row); if (bytesRead != row.Length) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel row"); @@ -737,10 +734,10 @@ private void ReadBgra32Row(int width, Buffer2D pixels, Span(Span palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow) + private void ReadPalettedBgra16Pixel(BufferedReadStream stream, Span palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow) where TPixel : unmanaged, IPixel { - int colorIndex = this.currentStream.ReadByte(); + int colorIndex = stream.ReadByte(); if (colorIndex == -1) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read color index"); @@ -767,10 +764,10 @@ private void ReadPalettedBgra16Pixel(Span palette, int index, int } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadPalettedBgr24Pixel(Span palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow) + private void ReadPalettedBgr24Pixel(BufferedReadStream stream, Span palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow) where TPixel : unmanaged, IPixel { - int colorIndex = this.currentStream.ReadByte(); + int colorIndex = stream.ReadByte(); if (colorIndex == -1) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read color index"); @@ -781,10 +778,10 @@ private void ReadPalettedBgr24Pixel(Span palette, int colorMapPixe } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ReadPalettedBgra32Pixel(Span palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow) + private void ReadPalettedBgra32Pixel(BufferedReadStream stream, Span palette, int colorMapPixelSizeInBytes, int x, TPixel color, Span pixelRow) where TPixel : unmanaged, IPixel { - int colorIndex = this.currentStream.ReadByte(); + int colorIndex = stream.ReadByte(); if (colorIndex == -1) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read color index"); @@ -801,21 +798,21 @@ private void ReadPalettedBgra32Pixel(Span palette, int colorMapPix /// The height of the image. /// Buffer for uncompressed data. /// The bytes used per pixel. - private void UncompressRle(int width, int height, Span buffer, int bytesPerPixel) + private void UncompressRle(BufferedReadStream stream, int width, int height, Span buffer, int bytesPerPixel) { int uncompressedPixels = 0; Span pixel = this.scratchBuffer.AsSpan(0, bytesPerPixel); int totalPixels = width * height; while (uncompressedPixels < totalPixels) { - byte runLengthByte = (byte)this.currentStream.ReadByte(); + byte runLengthByte = (byte)stream.ReadByte(); // The high bit of a run length packet is set to 1. int highBit = runLengthByte >> 7; if (highBit == 1) { int runLength = runLengthByte & 127; - int bytesRead = this.currentStream.Read(pixel, 0, bytesPerPixel); + int bytesRead = stream.Read(pixel, 0, bytesPerPixel); if (bytesRead != bytesPerPixel) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel from the stream"); @@ -835,7 +832,7 @@ private void UncompressRle(int width, int height, Span buffer, int bytesPe int bufferIdx = uncompressedPixels * bytesPerPixel; for (int i = 0; i < runLength + 1; i++, uncompressedPixels++) { - int bytesRead = this.currentStream.Read(pixel, 0, bytesPerPixel); + int bytesRead = stream.Read(pixel, 0, bytesPerPixel); if (bytesRead != bytesPerPixel) { TgaThrowHelper.ThrowInvalidImageContentException("Not enough data to read a pixel from the stream"); @@ -916,13 +913,13 @@ private static bool InvertX(TgaImageOrigin origin) => /// /// The containing image data. /// The image origin. + [MemberNotNull(nameof(tgaMetadata))] + [MemberNotNull(nameof(metadata))] private TgaImageOrigin ReadFileHeader(BufferedReadStream stream) { - this.currentStream = stream; - Span buffer = stackalloc byte[TgaFileHeader.Size]; - this.currentStream.Read(buffer, 0, TgaFileHeader.Size); + stream.Read(buffer, 0, TgaFileHeader.Size); this.fileHeader = TgaFileHeader.Parse(buffer); this.metadata = new ImageMetadata(); this.tgaMetadata = this.metadata.GetTgaMetadata(); diff --git a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs index 016806db03..2b77be4415 100644 --- a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs @@ -25,7 +25,7 @@ internal sealed class TgaEncoderCore : IImageEncoderInternals /// /// The global configuration. /// - private Configuration configuration; + private Configuration? configuration; /// /// Reusable buffer for writing data. @@ -138,7 +138,7 @@ public void Encode(Image image, Stream stream, CancellationToken private void WriteImage(Stream stream, ImageFrame image) where TPixel : unmanaged, IPixel { - Buffer2D pixels = image.PixelBuffer; + Buffer2D pixels = image.PixelBuffer!; switch (this.bitsPerPixel) { case TgaBitsPerPixel.Pixel8: @@ -169,7 +169,7 @@ private void WriteRunLengthEncodedImage(Stream stream, ImageFrame { Rgba32 color = default; - Buffer2D pixels = image.PixelBuffer; + Buffer2D pixels = image.PixelBuffer!; for (int y = 0; y < image.Height; y++) { Span pixelRow = pixels.DangerousGetRowSpan(y); diff --git a/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs b/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs index 23f93a8249..13d4e784c9 100644 --- a/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Tga/TgaImageFormatDetector.cs @@ -12,7 +12,7 @@ public sealed class TgaImageFormatDetector : IImageFormatDetector public int HeaderSize => 16; /// - public IImageFormat DetectFormat(ReadOnlySpan header) + public IImageFormat? DetectFormat(ReadOnlySpan header) { return this.IsSupportedFileFormat(header) ? TgaFormat.Instance : null; } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/LzwCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/LzwCompressor.cs index ee034f7eee..53a8d811c2 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/LzwCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/LzwCompressor.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors; internal sealed class LzwCompressor : TiffBaseCompressor { - private TiffLzwEncoder lzwEncoder; + private TiffLzwEncoder? lzwEncoder; public LzwCompressor(Stream output, MemoryAllocator allocator, int width, int bitsPerPixel, TiffPredictor predictor) : base(output, allocator, width, bitsPerPixel, predictor) @@ -29,6 +29,8 @@ public override void CompressStrip(Span rows, int height) HorizontalPredictor.ApplyHorizontalPrediction(rows, this.BytesPerRow, this.BitsPerPixel); } + ArgumentNullException.ThrowIfNull(this.lzwEncoder); + this.lzwEncoder.Encode(rows, this.Output); } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs index 180d28de9b..12a23b248b 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/PackBitsCompressor.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors; internal sealed class PackBitsCompressor : TiffBaseCompressor { - private IMemoryOwner pixelData; + private IMemoryOwner? pixelData; public PackBitsCompressor(Stream output, MemoryAllocator allocator, int width, int bitsPerPixel) : base(output, allocator, width, bitsPerPixel) @@ -32,6 +32,8 @@ public override void CompressStrip(Span rows, int height) DebugGuard.IsTrue(rows.Length % height == 0, "Invalid height"); DebugGuard.IsTrue(this.BytesPerRow == rows.Length / height, "The widths must match"); + ArgumentNullException.ThrowIfNull(this.pixelData); + Span span = this.pixelData.GetSpan(); for (int i = 0; i < height; i++) { diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs index d6bb1e22d9..b9b0d7a4d0 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/T6BitCompressor.cs @@ -26,7 +26,7 @@ private static readonly (uint Length, uint Code)[] VerticalCodes = (7u, 2u) }; - private IMemoryOwner referenceLineBuffer; + private IMemoryOwner? referenceLineBuffer; /// /// Initializes a new instance of the class. @@ -52,6 +52,7 @@ public T6BitCompressor(Stream output, MemoryAllocator allocator, int width, int protected override void CompressStrip(Span pixelsAsGray, int height, Span compressedData) { // Initial reference line is all white. + ArgumentNullException.ThrowIfNull(this.referenceLineBuffer); Span referenceLine = this.referenceLineBuffer.GetSpan(); referenceLine.Fill(0xff); diff --git a/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs b/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs index 0c43f92555..56bb13f53a 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffCcittCompressor.cs @@ -175,7 +175,7 @@ internal abstract class TiffCcittCompressor : TiffBaseCompressor private byte bitPosition; - private IMemoryOwner compressedDataBuffer; + private IMemoryOwner? compressedDataBuffer; /// /// Initializes a new instance of the class. @@ -498,6 +498,7 @@ public override void CompressStrip(Span rows, int height) DebugGuard.IsTrue(rows.Length / height == this.Width, "Values must be equals"); DebugGuard.IsTrue(rows.Length % height == 0, "Values must be equals"); + ArgumentNullException.ThrowIfNull(this.compressedDataBuffer); this.compressedDataBuffer.Clear(); Span compressedData = this.compressedDataBuffer.GetSpan(); diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs index 4c377c8783..2ed2b45b6f 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs @@ -51,12 +51,12 @@ protected override void Decompress(BufferedReadStream stream, int byteCount, int })) { deframeStream.AllocateNewBytes(byteCount, true); - DeflateStream dataStream = deframeStream.CompressedStream; + DeflateStream? dataStream = deframeStream.CompressedStream; int totalRead = 0; while (totalRead < buffer.Length) { - int bytesRead = dataStream.Read(buffer, totalRead, buffer.Length - totalRead); + int bytesRead = dataStream!.Read(buffer, totalRead, buffer.Length - totalRead); if (bytesRead <= 0) { break; diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs index d67a61355d..fa719c6dc8 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs @@ -18,7 +18,7 @@ internal sealed class JpegTiffCompression : TiffBaseDecompressor { private readonly JpegDecoderOptions options; - private readonly byte[] jpegTables; + private readonly byte[]? jpegTables; private readonly TiffPhotometricInterpretation photometricInterpretation; @@ -36,7 +36,7 @@ public JpegTiffCompression( MemoryAllocator memoryAllocator, int width, int bitsPerPixel, - byte[] jpegTables, + byte[]? jpegTables, TiffPhotometricInterpretation photometricInterpretation) : base(memoryAllocator, width, bitsPerPixel) { @@ -89,7 +89,7 @@ protected override void Decompress(BufferedReadStream stream, int byteCount, int else { using var image = Image.Load(stream); - CopyImageBytesToBuffer(buffer, image.Frames.RootFrame.PixelBuffer); + CopyImageBytesToBuffer(buffer, image.Frames.RootFrame.PixelBuffer!); } } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs index 94cbe0b00c..b0599eb7d1 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/LzwString.cs @@ -10,7 +10,7 @@ public class LzwString { private static readonly LzwString Empty = new LzwString(0, 0, 0, null); - private readonly LzwString previous; + private readonly LzwString? previous; private readonly byte value; /// @@ -22,7 +22,7 @@ public LzwString(byte code) { } - private LzwString(byte value, byte firstChar, int length, LzwString previous) + private LzwString(byte value, byte firstChar, int length, LzwString? previous) { this.value = value; this.FirstChar = firstChar; @@ -74,7 +74,7 @@ public int WriteTo(Span buffer, int offset) return 1; } - LzwString e = this; + LzwString? e = this; int endIdx = this.Length - 1; if (endIdx >= buffer.Length) { @@ -83,7 +83,7 @@ public int WriteTo(Span buffer, int offset) for (int i = endIdx; i >= 0; i--) { - buffer[offset + i] = e.value; + buffer[offset + i] = e!.value; e = e.previous; } diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs index 0999f934b2..7b583e00db 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/PackBitsTiffCompression.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors; /// internal sealed class PackBitsTiffCompression : TiffBaseDecompressor { - private IMemoryOwner compressedDataMemory; + private IMemoryOwner? compressedDataMemory; /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs index 4e1c9c2f84..2f7367862a 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs @@ -33,7 +33,7 @@ public WebpTiffCompression(DecoderOptions options, MemoryAllocator memoryAllocat protected override void Decompress(BufferedReadStream stream, int byteCount, int stripHeight, Span buffer, CancellationToken cancellationToken) { using Image image = ((IImageDecoder)new WebpDecoder()).Decode(this.options, stream, cancellationToken); - CopyImageBytesToBuffer(buffer, image.Frames.RootFrame.PixelBuffer); + CopyImageBytesToBuffer(buffer, image.Frames.RootFrame.PixelBuffer!); } private static void CopyImageBytesToBuffer(Span buffer, Buffer2D pixelBuffer) diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs index e09b93c02a..a85672bb58 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs @@ -20,7 +20,7 @@ public static TiffBaseDecompressor Create( TiffColorType colorType, TiffPredictor predictor, FaxCompressionOptions faxOptions, - byte[] jpegTables, + byte[]? jpegTables, TiffFillOrder fillOrder, ByteOrder byteOrder) { diff --git a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs index 1e74e630ce..200239c9d7 100644 --- a/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs +++ b/src/ImageSharp/Formats/Tiff/ITiffEncoderOptions.cs @@ -42,5 +42,5 @@ internal interface ITiffEncoderOptions /// /// Gets the quantizer for creating a color palette image. /// - IQuantizer Quantizer { get; } + IQuantizer? Quantizer { get; } } diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba16161616TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba16161616TiffColor{TPixel}.cs index 0e060bed31..f5da43f7d5 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba16161616TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba16161616TiffColor{TPixel}.cs @@ -48,8 +48,8 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in bool hasAssociatedAlpha = this.extraSamplesType.HasValue && this.extraSamplesType == TiffExtraSampleType.AssociatedAlphaData; int offset = 0; - using IMemoryOwner vectors = hasAssociatedAlpha ? this.memoryAllocator.Allocate(width) : null; - Span vectorsSpan = hasAssociatedAlpha ? vectors.GetSpan() : Span.Empty; + using IMemoryOwner? vectors = hasAssociatedAlpha ? this.memoryAllocator.Allocate(width) : null; + Span vectorsSpan = hasAssociatedAlpha ? vectors!.GetSpan() : Span.Empty; for (int y = top; y < top + height; y++) { Span pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba8888TiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba8888TiffColor{TPixel}.cs index 6e844f435b..80e31b9513 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba8888TiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/Rgba8888TiffColor{TPixel}.cs @@ -35,8 +35,8 @@ public override void Decode(ReadOnlySpan data, Buffer2D pixels, in var color = default(TPixel); color.FromScaledVector4(Vector4.Zero); - using IMemoryOwner vectors = hasAssociatedAlpha ? this.memoryAllocator.Allocate(width) : null; - Span vectorsSpan = hasAssociatedAlpha ? vectors.GetSpan() : Span.Empty; + using IMemoryOwner? vectors = hasAssociatedAlpha ? this.memoryAllocator.Allocate(width) : null; + Span vectorsSpan = hasAssociatedAlpha ? vectors!.GetSpan() : Span.Empty; for (int y = top; y < top + height; y++) { Span pixelRow = pixels.DangerousGetRowSpan(y).Slice(left, width); diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs index 2ad1d8677b..b504d1de61 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/TiffColorDecoderFactory{TPixel}.cs @@ -15,10 +15,10 @@ public static TiffBaseColorDecoder Create( TiffColorType colorType, TiffBitsPerSample bitsPerSample, TiffExtraSampleType? extraSampleType, - ushort[] colorMap, - Rational[] referenceBlackAndWhite, - Rational[] ycbcrCoefficients, - ushort[] ycbcrSubSampling, + ushort[]? colorMap, + Rational[]? referenceBlackAndWhite, + Rational[]? ycbcrCoefficients, + ushort[]? ycbcrSubSampling, ByteOrder byteOrder) { switch (colorType) @@ -411,10 +411,10 @@ public static TiffBasePlanarColorDecoder CreatePlanar( TiffColorType colorType, TiffBitsPerSample bitsPerSample, TiffExtraSampleType? extraSampleType, - ushort[] colorMap, - Rational[] referenceBlackAndWhite, - Rational[] ycbcrCoefficients, - ushort[] ycbcrSubSampling, + ushort[]? colorMap, + Rational[]? referenceBlackAndWhite, + Rational[]? ycbcrCoefficients, + ushort[]? ycbcrSubSampling, ByteOrder byteOrder) { switch (colorType) diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrConverter.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrConverter.cs index 0a1cf6ab98..2b1151235a 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrConverter.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrConverter.cs @@ -30,7 +30,7 @@ internal class YCbCrConverter new(128, 1), new(255, 1) }; - public YCbCrConverter(Rational[] referenceBlackAndWhite, Rational[] coefficients) + public YCbCrConverter(Rational[]? referenceBlackAndWhite, Rational[]? coefficients) { referenceBlackAndWhite ??= DefaultReferenceBlackWhite; coefficients ??= DefaultLuma; diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrPlanarTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrPlanarTiffColor{TPixel}.cs index 791bfa438a..81a8870677 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrPlanarTiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrPlanarTiffColor{TPixel}.cs @@ -16,9 +16,9 @@ internal class YCbCrPlanarTiffColor : TiffBasePlanarColorDecoder { private readonly YCbCrConverter converter; - private readonly ushort[] ycbcrSubSampling; + private readonly ushort[]? ycbcrSubSampling; - public YCbCrPlanarTiffColor(Rational[] referenceBlackAndWhite, Rational[] coefficients, ushort[] ycbcrSubSampling) + public YCbCrPlanarTiffColor(Rational[]? referenceBlackAndWhite, Rational[]? coefficients, ushort[]? ycbcrSubSampling) { this.converter = new YCbCrConverter(referenceBlackAndWhite, coefficients); this.ycbcrSubSampling = ycbcrSubSampling; diff --git a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrTiffColor{TPixel}.cs b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrTiffColor{TPixel}.cs index 2e47698a67..e51a35b706 100644 --- a/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrTiffColor{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/PhotometricInterpretation/YCbCrTiffColor{TPixel}.cs @@ -18,9 +18,9 @@ internal class YCbCrTiffColor : TiffBaseColorDecoder private readonly YCbCrConverter converter; - private readonly ushort[] ycbcrSubSampling; + private readonly ushort[]? ycbcrSubSampling; - public YCbCrTiffColor(MemoryAllocator memoryAllocator, Rational[] referenceBlackAndWhite, Rational[] coefficients, ushort[] ycbcrSubSampling) + public YCbCrTiffColor(MemoryAllocator memoryAllocator, Rational[]? referenceBlackAndWhite, Rational[]? coefficients, ushort[]? ycbcrSubSampling) { this.memoryAllocator = memoryAllocator; this.converter = new YCbCrConverter(referenceBlackAndWhite, coefficients); diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs index 157561b743..fb35ef2de3 100644 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs @@ -125,7 +125,7 @@ public static bool TryParse(ushort[] value, out TiffBitsPerSample sample) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is TiffBitsPerSample sample && this.Equals(sample); /// diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index 60bce2174d..686fd4d7dc 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -38,11 +38,6 @@ internal class TiffDecoderCore : IImageDecoderInternals /// private readonly uint maxFrames; - /// - /// The stream to decode from. - /// - private BufferedReadStream inputStream; - /// /// Indicates the byte order of the stream. /// @@ -79,7 +74,7 @@ public TiffDecoderCore(DecoderOptions options) /// /// Gets or sets the lookup table for RGB palette colored images. /// - public ushort[] ColorMap { get; set; } + public ushort[]? ColorMap { get; set; } /// /// Gets or sets the photometric interpretation implementation to use when decoding the image. @@ -89,17 +84,17 @@ public TiffDecoderCore(DecoderOptions options) /// /// Gets or sets the reference black and white for decoding YCbCr pixel data. /// - public Rational[] ReferenceBlackAndWhite { get; set; } + public Rational[]? ReferenceBlackAndWhite { get; set; } /// /// Gets or sets the YCbCr coefficients. /// - public Rational[] YcbcrCoefficients { get; set; } + public Rational[]? YcbcrCoefficients { get; set; } /// /// Gets or sets the YCbCr sub sampling. /// - public ushort[] YcbcrSubSampling { get; set; } + public ushort[]? YcbcrSubSampling { get; set; } /// /// Gets or sets the compression used, when the image was encoded. @@ -124,7 +119,7 @@ public TiffDecoderCore(DecoderOptions options) /// /// Gets or sets the JPEG tables when jpeg compression is used. /// - public byte[] JpegTables { get; set; } + public byte[]? JpegTables { get; set; } /// /// Gets or sets the planar configuration type to use when decoding the image. @@ -150,7 +145,7 @@ public TiffDecoderCore(DecoderOptions options) public DecoderOptions Options { get; } /// - public Size Dimensions { get; private set; } + public Size? Dimensions { get; private set; } /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) @@ -159,7 +154,6 @@ public Image Decode(BufferedReadStream stream, CancellationToken var frames = new List>(); try { - this.inputStream = stream; var reader = new DirectoryReader(stream, this.configuration.MemoryAllocator); IEnumerable directories = reader.Read(); @@ -170,7 +164,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken foreach (ExifProfile ifd in directories) { cancellationToken.ThrowIfCancellationRequested(); - ImageFrame frame = this.DecodeFrame(ifd, cancellationToken); + ImageFrame frame = this.DecodeFrame(stream, ifd, cancellationToken); frames.Add(frame); if (++frameCount == this.maxFrames) @@ -208,7 +202,6 @@ public Image Decode(BufferedReadStream stream, CancellationToken /// public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { - this.inputStream = stream; var reader = new DirectoryReader(stream, this.configuration.MemoryAllocator); IEnumerable directories = reader.Read(); @@ -219,7 +212,7 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella int width = GetImageWidth(rootFrameExifProfile); int height = GetImageHeight(rootFrameExifProfile); - return new ImageInfo(new PixelTypeInfo((int)rootMetadata.BitsPerPixel), width, height, metadata); + return new ImageInfo(new PixelTypeInfo((int)rootMetadata.BitsPerPixel!), width, height, metadata); } /// @@ -229,7 +222,7 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella /// The IFD tags. /// The token to monitor cancellation. /// The tiff frame. - private ImageFrame DecodeFrame(ExifProfile tags, CancellationToken cancellationToken) + private ImageFrame DecodeFrame(BufferedReadStream stream, ExifProfile tags, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { var imageFrameMetaData = new ImageFrameMetadata(); @@ -247,17 +240,18 @@ private ImageFrame DecodeFrame(ExifProfile tags, CancellationTok int height = GetImageHeight(tags); var frame = new ImageFrame(this.configuration, width, height, imageFrameMetaData); - int rowsPerStrip = tags.GetValue(ExifTag.RowsPerStrip) != null ? (int)tags.GetValue(ExifTag.RowsPerStrip).Value : TiffConstants.RowsPerStripInfinity; + int rowsPerStrip = tags.GetValue(ExifTag.RowsPerStrip) != null ? (int)tags.GetValue(ExifTag.RowsPerStrip)!.Value : TiffConstants.RowsPerStripInfinity; - var stripOffsetsArray = (Array)tags.GetValueInternal(ExifTag.StripOffsets).GetValue(); - var stripByteCountsArray = (Array)tags.GetValueInternal(ExifTag.StripByteCounts).GetValue(); + var stripOffsetsArray = (Array)tags.GetValueInternal(ExifTag.StripOffsets)!.GetValue()!; + var stripByteCountsArray = (Array)tags.GetValueInternal(ExifTag.StripByteCounts)!.GetValue()!; - using IMemoryOwner stripOffsetsMemory = this.ConvertNumbers(stripOffsetsArray, out Span stripOffsets); - using IMemoryOwner stripByteCountsMemory = this.ConvertNumbers(stripByteCountsArray, out Span stripByteCounts); + using IMemoryOwner? stripOffsetsMemory = this.ConvertNumbers(stripOffsetsArray, out Span stripOffsets); + using IMemoryOwner? stripByteCountsMemory = this.ConvertNumbers(stripByteCountsArray, out Span stripByteCounts); if (this.PlanarConfiguration == TiffPlanarConfiguration.Planar) { this.DecodeStripsPlanar( + stream, frame, rowsPerStrip, stripOffsets, @@ -267,6 +261,7 @@ private ImageFrame DecodeFrame(ExifProfile tags, CancellationTok else { this.DecodeStripsChunky( + stream, frame, rowsPerStrip, stripOffsets, @@ -277,7 +272,7 @@ private ImageFrame DecodeFrame(ExifProfile tags, CancellationTok return frame; } - private IMemoryOwner ConvertNumbers(Array array, out Span span) + private IMemoryOwner? ConvertNumbers(Array array, out Span span) { if (array is Number[] numbers) { @@ -349,14 +344,14 @@ private int CalculateStripBufferSize(int width, int height, int plane = -1) /// An array of byte offsets to each strip in the image. /// An array of the size of each strip (in bytes). /// The token to monitor cancellation. - private void DecodeStripsPlanar(ImageFrame frame, int rowsPerStrip, Span stripOffsets, Span stripByteCounts, CancellationToken cancellationToken) + private void DecodeStripsPlanar(BufferedReadStream stream, ImageFrame frame, int rowsPerStrip, Span stripOffsets, Span stripByteCounts, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { int stripsPerPixel = this.BitsPerSample.Channels; int stripsPerPlane = stripOffsets.Length / stripsPerPixel; int bitsPerPixel = this.BitsPerPixel; - Buffer2D pixels = frame.PixelBuffer; + Buffer2D pixels = frame.PixelBuffer!; var stripBuffers = new IMemoryOwner[stripsPerPixel]; @@ -402,7 +397,7 @@ private void DecodeStripsPlanar(ImageFrame frame, int rowsPerStr for (int planeIndex = 0; planeIndex < stripsPerPixel; planeIndex++) { decompressor.Decompress( - this.inputStream, + stream, stripOffsets[stripIndex], stripByteCounts[stripIndex], stripHeight, @@ -433,7 +428,7 @@ private void DecodeStripsPlanar(ImageFrame frame, int rowsPerStr /// The strip offsets. /// The strip byte counts. /// The token to monitor cancellation. - private void DecodeStripsChunky(ImageFrame frame, int rowsPerStrip, Span stripOffsets, Span stripByteCounts, CancellationToken cancellationToken) + private void DecodeStripsChunky(BufferedReadStream stream, ImageFrame frame, int rowsPerStrip, Span stripOffsets, Span stripByteCounts, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { // If the rowsPerStrip has the default value, which is effectively infinity. That is, the entire image is one strip. @@ -447,7 +442,7 @@ private void DecodeStripsChunky(ImageFrame frame, int rowsPerStr using IMemoryOwner stripBuffer = this.memoryAllocator.Allocate(uncompressedStripSize, AllocationOptions.Clean); Span stripBufferSpan = stripBuffer.GetSpan(); - Buffer2D pixels = frame.PixelBuffer; + Buffer2D pixels = frame.PixelBuffer!; using TiffBaseDecompressor decompressor = TiffDecompressorsFactory.Create( this.Options, @@ -491,7 +486,7 @@ private void DecodeStripsChunky(ImageFrame frame, int rowsPerStr } decompressor.Decompress( - this.inputStream, + stream, stripOffsets[stripIndex], stripByteCounts[stripIndex], stripHeight, @@ -509,7 +504,7 @@ private void DecodeStripsChunky(ImageFrame frame, int rowsPerStr /// The image width. private static int GetImageWidth(ExifProfile exifProfile) { - IExifValue width = exifProfile.GetValue(ExifTag.ImageWidth); + IExifValue? width = exifProfile.GetValue(ExifTag.ImageWidth); if (width == null) { TiffThrowHelper.ThrowImageFormatException("The TIFF image frame is missing the ImageWidth"); @@ -527,7 +522,7 @@ private static int GetImageWidth(ExifProfile exifProfile) /// The image height. private static int GetImageHeight(ExifProfile exifProfile) { - IExifValue height = exifProfile.GetValue(ExifTag.ImageLength); + IExifValue? height = exifProfile.GetValue(ExifTag.ImageLength); if (height == null) { TiffThrowHelper.ThrowImageFormatException("The TIFF image frame is missing the ImageLength"); diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs index 85444e6568..c82b26d91c 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -32,18 +33,18 @@ public static ImageMetadata Create(List> frames, bool { ImageFrame frame = frames[i]; ImageFrameMetadata frameMetaData = frame.Metadata; - if (TryGetIptc(frameMetaData.ExifProfile.Values, out byte[] iptcBytes)) + if (TryGetIptc(frameMetaData.ExifProfile!.Values, out byte[]? iptcBytes)) { frameMetaData.IptcProfile = new IptcProfile(iptcBytes); } - IExifValue xmpProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.XMP); + IExifValue? xmpProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.XMP); if (xmpProfileBytes != null) { frameMetaData.XmpProfile = new XmpProfile(xmpProfileBytes.Value); } - IExifValue iccProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.IccProfile); + IExifValue? iccProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.IccProfile); if (iccProfileBytes != null) { frameMetaData.IccProfile = new IccProfile(iccProfileBytes.Value); @@ -54,7 +55,7 @@ public static ImageMetadata Create(List> frames, bool return imageMetaData; } - public static ImageMetadata Create(ByteOrder byteOrder, bool isBigTiff, ExifProfile exifProfile) + public static ImageMetadata Create(ByteOrder byteOrder, bool isBigTiff, ExifProfile? exifProfile) { var imageMetaData = new ImageMetadata(); SetResolution(imageMetaData, exifProfile); @@ -66,7 +67,7 @@ public static ImageMetadata Create(ByteOrder byteOrder, bool isBigTiff, ExifProf return imageMetaData; } - private static void SetResolution(ImageMetadata imageMetaData, ExifProfile exifProfile) + private static void SetResolution(ImageMetadata imageMetaData, ExifProfile? exifProfile) { imageMetaData.ResolutionUnits = exifProfile != null ? UnitConverter.ExifProfileToResolutionUnit(exifProfile) : PixelResolutionUnit.PixelsPerInch; double? horizontalResolution = exifProfile?.GetValue(ExifTag.XResolution)?.Value.ToDouble(); @@ -82,23 +83,23 @@ private static void SetResolution(ImageMetadata imageMetaData, ExifProfile exifP } } - private static bool TryGetIptc(IReadOnlyList exifValues, out byte[] iptcBytes) + private static bool TryGetIptc(IReadOnlyList exifValues, [NotNullWhen(true)]out byte[]? iptcBytes) { iptcBytes = null; - IExifValue iptc = exifValues.FirstOrDefault(f => f.Tag == ExifTag.IPTC); + IExifValue? iptc = exifValues.FirstOrDefault(f => f.Tag == ExifTag.IPTC); if (iptc != null) { if (iptc.DataType == ExifDataType.Byte || iptc.DataType == ExifDataType.Undefined) { - iptcBytes = (byte[])iptc.GetValue(); + iptcBytes = (byte[])iptc.GetValue()!; return true; } // Some Encoders write the data type of IPTC as long. if (iptc.DataType == ExifDataType.Long) { - uint[] iptcValues = (uint[])iptc.GetValue(); + uint[] iptcValues = (uint[])iptc.GetValue()!; iptcBytes = new byte[iptcValues.Length * 4]; Buffer.BlockCopy(iptcValues, 0, iptcBytes, 0, iptcValues.Length * 4); if (iptcBytes[0] == 0x1c) diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs index 7593840bbb..e0f38b73df 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs @@ -28,10 +28,10 @@ public static void VerifyAndParse(this TiffDecoderCore options, ExifProfile exif TiffThrowHelper.ThrowNotSupported("Tiled images are not supported."); } - IExifValue extraSamplesExifValue = exifProfile.GetValueInternal(ExifTag.ExtraSamples); + IExifValue? extraSamplesExifValue = exifProfile.GetValueInternal(ExifTag.ExtraSamples); if (extraSamplesExifValue is not null) { - short[] extraSamples = (short[])extraSamplesExifValue.GetValue(); + short[] extraSamples = (short[])extraSamplesExifValue.GetValue()!; if (extraSamples.Length != 1) { TiffThrowHelper.ThrowNotSupported("ExtraSamples is only supported with one extra sample for alpha data."); @@ -56,7 +56,7 @@ public static void VerifyAndParse(this TiffDecoderCore options, ExifProfile exif TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported."); } - TiffSampleFormat[] sampleFormats = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray(); + TiffSampleFormat[]? sampleFormats = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray(); TiffSampleFormat? sampleFormat = null; if (sampleFormats != null) { @@ -70,7 +70,7 @@ public static void VerifyAndParse(this TiffDecoderCore options, ExifProfile exif } } - ushort[] ycbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value; + ushort[]? ycbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value; if (ycbcrSubSampling != null && ycbcrSubSampling.Length != 2) { TiffThrowHelper.ThrowImageFormatException("Invalid YCbCrSubsampling, expected 2 values."); @@ -454,7 +454,7 @@ private static void ParseCompression(this TiffDecoderCore options, TiffCompressi case TiffCompression.CcittGroup3Fax: { options.CompressionType = TiffDecoderCompressionType.T4; - options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None; + options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options)!.Value : FaxCompressionOptions.None; break; } @@ -462,7 +462,7 @@ private static void ParseCompression(this TiffDecoderCore options, TiffCompressi case TiffCompression.CcittGroup4Fax: { options.CompressionType = TiffDecoderCompressionType.T6; - options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None; + options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options)!.Value : FaxCompressionOptions.None; break; } diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs index 3b5d347722..d744b834f3 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoder.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoder.cs @@ -30,7 +30,7 @@ public class TiffEncoder : IImageEncoder, ITiffEncoderOptions public TiffPredictor? HorizontalPredictor { get; set; } /// - public IQuantizer Quantizer { get; set; } + public IQuantizer? Quantizer { get; set; } /// public void Encode(Image image, Stream stream) diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 971353dbc8..988310c44c 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -37,7 +37,7 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals /// /// The global configuration. /// - private Configuration configuration; + private Configuration? configuration; /// /// The quantizer for creating color palette image. @@ -147,7 +147,7 @@ public void Encode(Image image, Stream stream, CancellationToken using TiffStreamWriter writer = new(stream); long ifdMarker = WriteHeader(writer); - Image metadataImage = image; + Image? metadataImage = image; foreach (ImageFrame frame in image.Frames) { cancellationToken.ThrowIfCancellationRequested(); @@ -197,7 +197,7 @@ private long WriteFrame( TiffStreamWriter writer, ImageFrame frame, ImageMetadata imageMetadata, - Image image, + Image? image, long ifdOffset) where TPixel : unmanaged, IPixel { @@ -206,11 +206,12 @@ private long WriteFrame( writer.BaseStream, this.memoryAllocator, frame.Width, - (int)this.BitsPerPixel, + (int)this.BitsPerPixel!, this.compressionLevel, this.HorizontalPredictor == TiffPredictor.Horizontal ? this.HorizontalPredictor.Value : TiffPredictor.None); TiffEncoderEntriesCollector entriesCollector = new(); + ArgumentNullException.ThrowIfNull(this.configuration); using TiffBaseColorWriter colorWriter = TiffColorWriterFactory.Create( this.PhotometricInterpretation, frame, diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs index e158900cdc..3928825fa4 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs @@ -57,7 +57,7 @@ public void Process(Image image) { ImageFrame rootFrame = image.Frames.RootFrame; ExifProfile rootFrameExifProfile = rootFrame.Metadata.ExifProfile ?? new ExifProfile(); - XmpProfile rootFrameXmpProfile = rootFrame.Metadata.XmpProfile; + XmpProfile? rootFrameXmpProfile = rootFrame.Metadata.XmpProfile; this.ProcessProfiles(image.Metadata, rootFrameExifProfile, rootFrameXmpProfile); this.ProcessMetadata(rootFrameExifProfile); @@ -149,7 +149,7 @@ private void ProcessMetadata(ExifProfile exifProfile) } } - private void ProcessProfiles(ImageMetadata imageMetadata, ExifProfile exifProfile, XmpProfile xmpProfile) + private void ProcessProfiles(ImageMetadata imageMetadata, ExifProfile? exifProfile, XmpProfile? xmpProfile) { if (exifProfile != null && exifProfile.Parts != ExifParts.None) { @@ -167,7 +167,7 @@ private void ProcessProfiles(ImageMetadata imageMetadata, ExifProfile exifProfil } else { - exifProfile.RemoveValue(ExifTag.SubIFDOffset); + exifProfile?.RemoveValue(ExifTag.SubIFDOffset); } if (imageMetadata.IptcProfile != null) @@ -182,7 +182,7 @@ private void ProcessProfiles(ImageMetadata imageMetadata, ExifProfile exifProfil } else { - exifProfile.RemoveValue(ExifTag.IPTC); + exifProfile?.RemoveValue(ExifTag.IPTC); } if (imageMetadata.IccProfile != null) @@ -196,7 +196,7 @@ private void ProcessProfiles(ImageMetadata imageMetadata, ExifProfile exifProfil } else { - exifProfile.RemoveValue(ExifTag.IccProfile); + exifProfile?.RemoveValue(ExifTag.IccProfile); } if (xmpProfile != null) @@ -210,7 +210,7 @@ private void ProcessProfiles(ImageMetadata imageMetadata, ExifProfile exifProfil } else { - exifProfile.RemoveValue(ExifTag.XMP); + exifProfile?.RemoveValue(ExifTag.XMP); } } } @@ -297,7 +297,7 @@ public void Process(TiffEncoderCore encoder) var photometricInterpretation = new ExifShort(ExifTagValue.PhotometricInterpretation) { - Value = (ushort)encoder.PhotometricInterpretation + Value = (ushort)encoder.PhotometricInterpretation! }; this.Collector.AddOrReplace(planarConfig); diff --git a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs index ee8ba1ce01..a29ab6dd36 100644 --- a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs +++ b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs @@ -73,11 +73,11 @@ internal static TiffFrameMetadata Parse(ExifProfile profile) /// /// The tiff frame meta data. /// The Exif profile containing tiff frame directory tags. - internal static void Parse(TiffFrameMetadata meta, ExifProfile profile) + internal static void Parse(TiffFrameMetadata meta, ExifProfile? profile) { if (profile != null) { - if (TiffBitsPerSample.TryParse(profile.GetValue(ExifTag.BitsPerSample)?.Value, out TiffBitsPerSample bitsPerSample)) + if (TiffBitsPerSample.TryParse(profile.GetValue(ExifTag.BitsPerSample)!.Value!, out TiffBitsPerSample bitsPerSample)) { meta.BitsPerSample = bitsPerSample; } diff --git a/src/ImageSharp/Formats/Tiff/TiffImageFormatDetector.cs b/src/ImageSharp/Formats/Tiff/TiffImageFormatDetector.cs index 24166f6c0f..9af6a659e3 100644 --- a/src/ImageSharp/Formats/Tiff/TiffImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Tiff/TiffImageFormatDetector.cs @@ -12,7 +12,7 @@ public sealed class TiffImageFormatDetector : IImageFormatDetector public int HeaderSize => 8; /// - public IImageFormat DetectFormat(ReadOnlySpan header) + public IImageFormat? DetectFormat(ReadOnlySpan header) { if (this.IsSupportedFileFormat(header)) { diff --git a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs index b2cc638ba0..949763b206 100644 --- a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs +++ b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs @@ -1,10 +1,13 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Formats.Tiff; internal static class TiffThrowHelper { + [DoesNotReturn] public static Exception ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage); public static Exception NotSupportedDecompressor(string compressionType) => throw new NotSupportedException($"Not supported decoder compression method: {compressionType}"); diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs index 28e3123dba..2317467fb8 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffBiColorWriter{TPixel}.cs @@ -16,9 +16,9 @@ internal sealed class TiffBiColorWriter : TiffBaseColorWriter { private readonly Image imageBlackWhite; - private IMemoryOwner pixelsAsGray; + private IMemoryOwner? pixelsAsGray; - private IMemoryOwner bitStrip; + private IMemoryOwner? bitStrip; public TiffBiColorWriter(ImageFrame image, MemoryAllocator memoryAllocator, Configuration configuration, TiffEncoderEntriesCollector entriesCollector) : base(image, memoryAllocator, configuration, entriesCollector) @@ -67,7 +67,7 @@ protected override void EncodeStrip(int y, int height, TiffBaseCompressor compre Span rows = this.bitStrip.Slice(0, bytesPerStrip); rows.Clear(); - Buffer2D blackWhiteBuffer = this.imageBlackWhite.Frames.RootFrame.PixelBuffer; + Buffer2D blackWhiteBuffer = this.imageBlackWhite.Frames.RootFrame.PixelBuffer!; int outputRowIdx = 0; int lastRow = y + height; diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffCompositeColorWriter{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffCompositeColorWriter{TPixel}.cs index 3ead7960cb..d994ab1348 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffCompositeColorWriter{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffCompositeColorWriter{TPixel}.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers; internal abstract class TiffCompositeColorWriter : TiffBaseColorWriter where TPixel : unmanaged, IPixel { - private IMemoryOwner rowBuffer; + private IMemoryOwner? rowBuffer; protected TiffCompositeColorWriter(ImageFrame image, MemoryAllocator memoryAllocator, Configuration configuration, TiffEncoderEntriesCollector entriesCollector) : base(image, memoryAllocator, configuration, entriesCollector) @@ -39,7 +39,7 @@ protected override void EncodeStrip(int y, int height, TiffBaseCompressor compre int stripPixelsRowIdx = 0; for (int row = y; row < lastRow; row++) { - Span stripPixelsRow = this.Image.PixelBuffer.DangerousGetRowSpan(row); + Span stripPixelsRow = this.Image.PixelBuffer!.DangerousGetRowSpan(row); stripPixelsRow.CopyTo(stripPixels.Slice(stripPixelsRowIdx * width, width)); stripPixelsRowIdx++; } diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter{TPixel}.cs index f8810d65ac..4f88548491 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter{TPixel}.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffPaletteWriter{TPixel}.cs @@ -18,7 +18,7 @@ internal sealed class TiffPaletteWriter : TiffBaseColorWriter private readonly int colorPaletteSize; private readonly int colorPaletteBytes; private readonly IndexedImageFrame quantizedImage; - private IMemoryOwner indexedPixelsBuffer; + private IMemoryOwner? indexedPixelsBuffer; public TiffPaletteWriter( ImageFrame image, diff --git a/src/ImageSharp/Formats/Webp/AlphaDecoder.cs b/src/ImageSharp/Formats/Webp/AlphaDecoder.cs index 4eb2aef4cf..ccde3d11eb 100644 --- a/src/ImageSharp/Formats/Webp/AlphaDecoder.cs +++ b/src/ImageSharp/Formats/Webp/AlphaDecoder.cs @@ -61,6 +61,7 @@ public AlphaDecoder(int width, int height, IMemoryOwner data, byte alphaCh var bitReader = new Vp8LBitReader(data); this.LosslessDecoder = new WebpLosslessDecoder(bitReader, memoryAllocator, configuration); this.LosslessDecoder.DecodeImageStream(this.Vp8LDec, width, height, true); + ArgumentNullException.ThrowIfNull(this.Vp8LDec.Transforms); this.Use8BDecode = this.Vp8LDec.Transforms.Count > 0 && Is8BOptimizable(this.Vp8LDec.Metadata); } } @@ -113,7 +114,7 @@ public AlphaDecoder(int width, int height, IMemoryOwner data, byte alphaCh /// /// Gets the Vp8L decoder which is used to de compress the alpha channel, if needed. /// - private WebpLosslessDecoder LosslessDecoder { get; } + private WebpLosslessDecoder? LosslessDecoder { get; } /// /// Gets a value indicating whether the decoding needs 1 byte per pixel for decoding. @@ -170,11 +171,11 @@ public void Decode() { if (this.Use8BDecode) { - this.LosslessDecoder.DecodeAlphaData(this); + this.LosslessDecoder!.DecodeAlphaData(this); } else { - this.LosslessDecoder.DecodeImageData(this.Vp8LDec, this.Vp8LDec.Pixels.Memory.Span); + this.LosslessDecoder!.DecodeImageData(this.Vp8LDec, this.Vp8LDec.Pixels.Memory.Span); this.ExtractAlphaRows(this.Vp8LDec); } } @@ -233,6 +234,8 @@ public void ExtractPalettedAlphaRows(int lastRow) Span dst = output[(this.Width * firstRow)..]; Span input = pixelDataAsBytes[(this.Vp8LDec.Width * firstRow)..]; + ArgumentNullException.ThrowIfNull(this.Vp8LDec.Transforms); + if (this.Vp8LDec.Transforms.Count == 0 || this.Vp8LDec.Transforms[0].TransformType != Vp8LTransformType.ColorIndexingTransform) { WebpThrowHelper.ThrowImageFormatException("error while decoding alpha channel, expected color index transform data is missing"); @@ -274,6 +277,7 @@ private static void ColorIndexInverseTransformAlpha( { int bitsPerPixel = 8 >> transform.Bits; int width = transform.XSize; + ArgumentNullException.ThrowIfNull(transform.Data); Span colorMap = transform.Data.Memory.Span; if (bitsPerPixel < 8) { @@ -424,7 +428,7 @@ private static bool Is8BOptimizable(Vp8LMetadata hdr) for (int i = 0; i < hdr.NumHTreeGroups; i++) { - List htrees = hdr.HTreeGroups[i].HTrees; + List htrees = hdr.HTreeGroups![i].HTrees; if (htrees[HuffIndex.Red][0].BitsUsed > 0) { return false; diff --git a/src/ImageSharp/Formats/Webp/AlphaEncoder.cs b/src/ImageSharp/Formats/Webp/AlphaEncoder.cs index 1e60235e26..f80b75fa59 100644 --- a/src/ImageSharp/Formats/Webp/AlphaEncoder.cs +++ b/src/ImageSharp/Formats/Webp/AlphaEncoder.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Formats.Webp; /// internal class AlphaEncoder : IDisposable { - private IMemoryOwner alphaData; + private IMemoryOwner? alphaData; /// /// Encodes the alpha channel data. @@ -103,7 +103,7 @@ private static Image DispatchAlphaToGreen(Image image, S private static IMemoryOwner ExtractAlphaChannel(Image image, Configuration configuration, MemoryAllocator memoryAllocator) where TPixel : unmanaged, IPixel { - Buffer2D imageBuffer = image.Frames.RootFrame.PixelBuffer; + Buffer2D imageBuffer = image.Frames.RootFrame.PixelBuffer!; int height = image.Height; int width = image.Width; IMemoryOwner alphaDataBuffer = memoryAllocator.Allocate(width * height); diff --git a/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs b/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs index b88dac8ede..fa121be4f5 100644 --- a/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs +++ b/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System.Buffers; +using System.Diagnostics.CodeAnalysis; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Formats.Webp.BitReader; @@ -16,7 +17,7 @@ internal abstract class BitReaderBase : IDisposable /// /// Gets or sets the raw encoded image data. /// - public IMemoryOwner Data { get; set; } + public IMemoryOwner? Data { get; set; } /// /// Copies the raw encoded image data from the stream into a byte array. @@ -24,6 +25,7 @@ internal abstract class BitReaderBase : IDisposable /// The input stream. /// Number of bytes to read as indicated from the chunk size. /// Used for allocating memory during reading data from the stream. + [MemberNotNull(nameof(Data))] protected void ReadImageDataFromStream(Stream input, int bytesToRead, MemoryAllocator memoryAllocator) { this.Data = memoryAllocator.Allocate(bytesToRead); diff --git a/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs b/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs index 07bfcccd91..1fa4deda97 100644 --- a/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs +++ b/src/ImageSharp/Formats/Webp/BitReader/Vp8BitReader.cs @@ -186,7 +186,7 @@ private void LoadNewBytes() { if (this.pos < this.bufferMax) { - ulong inBits = BinaryPrimitives.ReadUInt64LittleEndian(this.Data.Memory.Span.Slice((int)this.pos, 8)); + ulong inBits = BinaryPrimitives.ReadUInt64LittleEndian(this.Data!.Memory.Span.Slice((int)this.pos, 8)); this.pos += BitsCount >> 3; ulong bits = ByteSwap64(inBits); bits >>= 64 - BitsCount; @@ -205,7 +205,7 @@ private void LoadFinalBytes() if (this.pos < this.bufferEnd) { this.bits += 8; - this.value = this.Data.Memory.Span[(int)this.pos++] | (this.value << 8); + this.value = this.Data!.Memory.Span[(int)this.pos++] | (this.value << 8); } else if (!this.eof) { diff --git a/src/ImageSharp/Formats/Webp/BitReader/Vp8LBitReader.cs b/src/ImageSharp/Formats/Webp/BitReader/Vp8LBitReader.cs index 057abf134a..df95f01f4a 100644 --- a/src/ImageSharp/Formats/Webp/BitReader/Vp8LBitReader.cs +++ b/src/ImageSharp/Formats/Webp/BitReader/Vp8LBitReader.cs @@ -193,7 +193,7 @@ public void FillBitWindow() [MethodImpl(InliningOptions.ShortMethod)] private void ShiftBytes() { - System.Span dataSpan = this.Data.Memory.Span; + System.Span dataSpan = this.Data!.Memory.Span; while (this.bitPos >= 8 && this.pos < this.len) { this.value >>= 8; diff --git a/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs b/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs index 2df02727e0..0a47d676d9 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/BitWriterBase.cs @@ -207,7 +207,7 @@ protected void WriteColorProfile(Stream stream, byte[] iccProfileBytes) /// The width of the image. /// The height of the image. /// Flag indicating, if a alpha channel is present. - protected void WriteVp8XHeader(Stream stream, ExifProfile exifProfile, XmpProfile xmpProfile, byte[] iccProfileBytes, uint width, uint height, bool hasAlpha) + protected void WriteVp8XHeader(Stream stream, ExifProfile? exifProfile, XmpProfile? xmpProfile, byte[]? iccProfileBytes, uint width, uint height, bool hasAlpha) { if (width > MaxDimension || height > MaxDimension) { diff --git a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs index 87f993d93f..cd8f04e7d1 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/Vp8BitWriter.cs @@ -33,7 +33,7 @@ internal class Vp8BitWriter : BitWriterBase private const int B_HU_PRED = 9; #pragma warning restore SA1310 // Field names should not contain underscore - private readonly Vp8Encoder enc; + private readonly Vp8Encoder? enc; private int range; @@ -82,7 +82,7 @@ public Vp8BitWriter(int expectedSize, Vp8Encoder enc) public int PutCoeffs(int ctx, Vp8Residual residual) { int n = residual.First; - Vp8ProbaArray p = residual.Prob[n].Probabilities[ctx]; + Vp8ProbaArray p = residual.Prob![n].Probabilities[ctx]; if (!this.PutBit(residual.Last >= 0, p.Probabilities[0])) { return 0; @@ -413,9 +413,9 @@ private void Flush() /// Indicates, if the alpha data is compressed. public void WriteEncodedImageToStream( Stream stream, - ExifProfile exifProfile, - XmpProfile xmpProfile, - IccProfile iccProfile, + ExifProfile? exifProfile, + XmpProfile? xmpProfile, + IccProfile? iccProfile, uint width, uint height, bool hasAlpha, @@ -423,9 +423,9 @@ public void WriteEncodedImageToStream( bool alphaDataIsCompressed) { bool isVp8X = false; - byte[] exifBytes = null; - byte[] xmpBytes = null; - byte[] iccProfileBytes = null; + byte[]? exifBytes = null; + byte[]? xmpBytes = null; + byte[]? iccProfileBytes = null; uint riffSize = 0; if (exifProfile != null) { @@ -438,7 +438,7 @@ public void WriteEncodedImageToStream( { isVp8X = true; xmpBytes = xmpProfile.Data; - riffSize += MetadataChunkSize(xmpBytes); + riffSize += MetadataChunkSize(xmpBytes!); } if (iccProfile != null) @@ -461,6 +461,7 @@ public void WriteEncodedImageToStream( this.Finish(); uint numBytes = (uint)this.NumBytes(); + ArgumentNullException.ThrowIfNull(this.enc); int mbSize = this.enc.Mbw * this.enc.Mbh; int expectedSize = mbSize * 7 / 8; @@ -489,12 +490,12 @@ public void WriteEncodedImageToStream( stream.WriteByte(0); } - if (exifProfile != null) + if (exifProfile != null && exifBytes != null) { this.WriteMetadataProfile(stream, exifBytes, WebpChunkType.Exif); } - if (xmpProfile != null) + if (xmpProfile != null && xmpBytes != null) { this.WriteMetadataProfile(stream, xmpBytes, WebpChunkType.Xmp); } @@ -522,6 +523,8 @@ private uint GeneratePartition0(Vp8BitWriter bitWriter) private void WriteSegmentHeader(Vp8BitWriter bitWriter) { + ArgumentNullException.ThrowIfNull(this.enc); + ArgumentNullException.ThrowIfNull(this.enc.SegmentHeader); Vp8EncSegmentHeader hdr = this.enc.SegmentHeader; Vp8EncProba proba = this.enc.Proba; if (bitWriter.PutBitUniform(hdr.NumSegments > 1 ? 1 : 0) != 0) @@ -559,6 +562,7 @@ private void WriteSegmentHeader(Vp8BitWriter bitWriter) private void WriteFilterHeader(Vp8BitWriter bitWriter) { + ArgumentNullException.ThrowIfNull(this.enc); Vp8FilterHeader hdr = this.enc.FilterHeader; bool useLfDelta = hdr.I4x4LfDelta != 0; bitWriter.PutBitUniform(hdr.Simple ? 1 : 0); @@ -583,6 +587,7 @@ private void WriteFilterHeader(Vp8BitWriter bitWriter) // Nominal quantization parameters private void WriteQuant(Vp8BitWriter bitWriter) { + ArgumentNullException.ThrowIfNull(this.enc); bitWriter.PutBits((uint)this.enc.BaseQuant, 7); bitWriter.PutSignedBits(this.enc.DqY1Dc, 4); bitWriter.PutSignedBits(this.enc.DqY2Dc, 4); @@ -593,6 +598,7 @@ private void WriteQuant(Vp8BitWriter bitWriter) private void WriteProbas(Vp8BitWriter bitWriter) { + ArgumentNullException.ThrowIfNull(this.enc); Vp8EncProba probas = this.enc.Proba; for (int t = 0; t < WebpConstants.NumTypes; ++t) { @@ -622,6 +628,7 @@ private void WriteProbas(Vp8BitWriter bitWriter) // Writes the partition #0 modes (that is: all intra modes) private void CodeIntraModes(Vp8BitWriter bitWriter) { + ArgumentNullException.ThrowIfNull(this.enc); var it = new Vp8EncIterator(this.enc.YTop, this.enc.UvTop, this.enc.Nz, this.enc.MbInfo, this.enc.Preds, this.enc.TopDerr, this.enc.Mbw, this.enc.Mbh); int predsWidth = this.enc.PredsWidth; @@ -630,6 +637,7 @@ private void CodeIntraModes(Vp8BitWriter bitWriter) Vp8MacroBlockInfo mb = it.CurrentMacroBlockInfo; int predIdx = it.PredIdx; Span preds = it.Preds.AsSpan(predIdx); + ArgumentNullException.ThrowIfNull(this.enc.SegmentHeader); if (this.enc.SegmentHeader.UpdateMap) { bitWriter.PutSegment(mb.Segment, this.enc.Proba.Segments); @@ -675,9 +683,9 @@ private void WriteWebpHeaders( bool isVp8X, uint width, uint height, - ExifProfile exifProfile, - XmpProfile xmpProfile, - byte[] iccProfileBytes, + ExifProfile? exifProfile, + XmpProfile? xmpProfile, + byte[]? iccProfileBytes, bool hasAlpha, Span alphaData, bool alphaDataIsCompressed) @@ -717,6 +725,7 @@ private void WriteVp8Header(Stream stream, uint size) private void WriteFrameHeader(Stream stream, uint size0) { uint profile = 0; + ArgumentNullException.ThrowIfNull(this.enc); int width = this.enc.Width; int height = this.enc.Height; byte[] vp8FrameHeader = new byte[WebpConstants.Vp8FrameHeaderSize]; diff --git a/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs b/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs index 5fbbeed114..3b4f874797 100644 --- a/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs +++ b/src/ImageSharp/Formats/Webp/BitWriter/Vp8LBitWriter.cs @@ -137,12 +137,12 @@ public override void Finish() /// The width of the image. /// The height of the image. /// Flag indicating, if a alpha channel is present. - public void WriteEncodedImageToStream(Stream stream, ExifProfile exifProfile, XmpProfile xmpProfile, IccProfile iccProfile, uint width, uint height, bool hasAlpha) + public void WriteEncodedImageToStream(Stream stream, ExifProfile? exifProfile, XmpProfile? xmpProfile, IccProfile? iccProfile, uint width, uint height, bool hasAlpha) { bool isVp8X = false; - byte[] exifBytes = null; - byte[] xmpBytes = null; - byte[] iccBytes = null; + byte[]? exifBytes = null; + byte[]? xmpBytes = null; + byte[]? iccBytes = null; uint riffSize = 0; if (exifProfile != null) { @@ -155,7 +155,7 @@ public void WriteEncodedImageToStream(Stream stream, ExifProfile exifProfile, Xm { isVp8X = true; xmpBytes = xmpProfile.Data; - riffSize += MetadataChunkSize(xmpBytes); + riffSize += MetadataChunkSize(xmpBytes!); } if (iccProfile != null) @@ -205,12 +205,12 @@ public void WriteEncodedImageToStream(Stream stream, ExifProfile exifProfile, Xm stream.WriteByte(0); } - if (exifProfile != null) + if (exifProfile != null && exifBytes != null) { this.WriteMetadataProfile(stream, exifBytes, WebpChunkType.Exif); } - if (xmpProfile != null) + if (xmpProfile != null && xmpBytes != null) { this.WriteMetadataProfile(stream, xmpBytes, WebpChunkType.Xmp); } diff --git a/src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs index 09908f6c38..ab42b99793 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs @@ -49,7 +49,7 @@ public static Vp8LBackwardRefs GetBackwardReferences( int lz77TypeBest = 0; double bitCostBest = -1; int cacheBitsInitial = cacheBits; - Vp8LHashChain hashChainBox = null; + Vp8LHashChain? hashChainBox = null; var stats = new Vp8LStreaks(); var bitsEntropy = new Vp8LBitEntropy(); for (int lz77Type = 1; lz77TypesToTry > 0; lz77TypesToTry &= ~lz77Type, lz77Type <<= 1) @@ -100,8 +100,8 @@ public static Vp8LBackwardRefs GetBackwardReferences( // Improve on simple LZ77 but only for high quality (TraceBackwards is costly). if ((lz77TypeBest == (int)Vp8LLz77Type.Lz77Standard || lz77TypeBest == (int)Vp8LLz77Type.Lz77Box) && quality >= 25) { - Vp8LHashChain hashChainTmp = lz77TypeBest == (int)Vp8LLz77Type.Lz77Standard ? hashChain : hashChainBox; - BackwardReferencesTraceBackwards(width, height, memoryAllocator, bgra, cacheBits, hashChainTmp, best, worst); + Vp8LHashChain? hashChainTmp = lz77TypeBest == (int)Vp8LLz77Type.Lz77Standard ? hashChain : hashChainBox; + BackwardReferencesTraceBackwards(width, height, memoryAllocator, bgra, cacheBits, hashChainTmp!, best, worst); var histo = new Vp8LHistogram(worst, cacheBits); double bitCostTrace = histo.EstimateBits(stats, bitsEntropy); if (bitCostTrace < bitCostBest) @@ -207,7 +207,10 @@ private static int CalculateBestCacheSize(ReadOnlySpan bgra, int quality, int key = ColorCache.HashPix(bgra[pos], 32 - cacheBitsMax); for (int i = cacheBitsMax; i >= 1; --i, key >>= 1) { - colorCache[i].Colors[key] = bgra[pos]; + uint[]? colors = colorCache[i].Colors; + ArgumentNullException.ThrowIfNull(colors); + + colors[key] = bgra[pos]; } bgraPrev = bgra[pos]; diff --git a/src/ImageSharp/Formats/Webp/Lossless/ColorCache.cs b/src/ImageSharp/Formats/Webp/Lossless/ColorCache.cs index 659da10686..1f26aa6871 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/ColorCache.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/ColorCache.cs @@ -15,7 +15,7 @@ internal class ColorCache /// /// Gets the color entries. /// - public uint[] Colors { get; private set; } + public uint[]? Colors { get; private set; } /// /// Gets the hash shift: 32 - hashBits. @@ -47,7 +47,7 @@ public void Init(int hashBits) public void Insert(uint bgra) { int key = HashPix(bgra, this.HashShift); - this.Colors[key] = bgra; + this.Colors![key] = bgra; } /// @@ -56,7 +56,11 @@ public void Insert(uint bgra) /// The key to lookup. /// The color for the key. [MethodImpl(InliningOptions.ShortMethod)] - public uint Lookup(int key) => this.Colors[key]; + public uint Lookup(int key) + { + ArgumentNullException.ThrowIfNull(this.Colors); + return this.Colors[key]; + } /// /// Returns the index of the given color. @@ -67,6 +71,7 @@ public void Insert(uint bgra) public int Contains(uint bgra) { int key = HashPix(bgra, this.HashShift); + ArgumentNullException.ThrowIfNull(this.Colors); return (this.Colors[key] == bgra) ? key : -1; } @@ -84,7 +89,11 @@ public int Contains(uint bgra) /// The key. /// The color to add. [MethodImpl(InliningOptions.ShortMethod)] - public void Set(uint key, uint bgra) => this.Colors[key] = bgra; + public void Set(uint key, uint bgra) + { + ArgumentNullException.ThrowIfNull(this.Colors); + this.Colors[key] = bgra; + } [MethodImpl(InliningOptions.ShortMethod)] public static int HashPix(uint argb, int shift) => (int)((argb * HashMul) >> shift); diff --git a/src/ImageSharp/Formats/Webp/Lossless/CostInterval.cs b/src/ImageSharp/Formats/Webp/Lossless/CostInterval.cs index bee5e4cc36..0cc4a30fd7 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/CostInterval.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/CostInterval.cs @@ -32,7 +32,7 @@ internal class CostInterval public int Index { get; set; } - public CostInterval Previous { get; set; } + public CostInterval? Previous { get; set; } - public CostInterval Next { get; set; } + public CostInterval? Next { get; set; } } diff --git a/src/ImageSharp/Formats/Webp/Lossless/CostManager.cs b/src/ImageSharp/Formats/Webp/Lossless/CostManager.cs index f852f2137c..538047c294 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/CostManager.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/CostManager.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless; /// internal sealed class CostManager : IDisposable { - private CostInterval head; + private CostInterval? head; private const int FreeIntervalsStartCount = 25; @@ -102,10 +102,10 @@ public CostManager(MemoryAllocator memoryAllocator, IMemoryOwner distArr /// If 'doCleanIntervals' is true, intervals that end before 'i' will be popped. public void UpdateCostAtIndex(int i, bool doCleanIntervals) { - CostInterval current = this.head; + CostInterval? current = this.head; while (current != null && current.Start <= i) { - CostInterval next = current.Next; + CostInterval? next = current.Next; if (current.End <= i) { if (doCleanIntervals) @@ -154,7 +154,7 @@ public void PushInterval(double distanceCost, int position, int len) return; } - CostInterval interval = this.head; + CostInterval? interval = this.head; for (int i = 0; i < this.CacheIntervalsSize && this.CacheIntervals[i].Start < len; i++) { // Define the intersection of the ith interval with the new one. @@ -162,7 +162,7 @@ public void PushInterval(double distanceCost, int position, int len) int end = position + (this.CacheIntervals[i].End > len ? len : this.CacheIntervals[i].End); float cost = (float)(distanceCost + this.CacheIntervals[i].Cost); - CostInterval intervalNext; + CostInterval? intervalNext; for (; interval != null && interval.Start < end; interval = intervalNext) { intervalNext = interval.Next; @@ -216,7 +216,7 @@ public void PushInterval(double distanceCost, int position, int len) } // Insert the remaining interval from start to end. - this.InsertInterval(interval, cost, position, start, end); + this.InsertInterval(interval!, cost, position, start, end); } } @@ -224,7 +224,7 @@ public void PushInterval(double distanceCost, int position, int len) /// Pop an interval from the manager. /// /// The interval to remove. - private void PopInterval(CostInterval interval) + private void PopInterval(CostInterval? interval) { if (interval == null) { @@ -270,7 +270,7 @@ private void InsertInterval(CostInterval intervalIn, float cost, int position, i /// it was orphaned (which can be NULL), set it at the right place in the list /// of intervals using the start_ ordering and the previous interval as a hint. /// - private void PositionOrphanInterval(CostInterval current, CostInterval previous) + private void PositionOrphanInterval(CostInterval current, CostInterval? previous) { previous ??= this.head; @@ -291,7 +291,7 @@ private void PositionOrphanInterval(CostInterval current, CostInterval previous) /// /// Given two intervals, make 'prev' be the previous one of 'next' in 'manager'. /// - private void ConnectIntervals(CostInterval prev, CostInterval next) + private void ConnectIntervals(CostInterval? prev, CostInterval? next) { if (prev != null) { diff --git a/src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs index 45cbcfa94f..3f601753c2 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs @@ -26,7 +26,7 @@ internal class HistogramEncoder private const ushort InvalidHistogramSymbol = ushort.MaxValue; - public static void GetHistoImageSymbols(int xSize, int ySize, Vp8LBackwardRefs refs, int quality, int histoBits, int cacheBits, List imageHisto, Vp8LHistogram tmpHisto, ushort[] histogramSymbols) + public static void GetHistoImageSymbols(int xSize, int ySize, Vp8LBackwardRefs refs, int quality, int histoBits, int cacheBits, List imageHisto, Vp8LHistogram tmpHisto, ushort[] histogramSymbols) { int histoXSize = histoBits > 0 ? LosslessUtils.SubSampleSize(xSize, histoBits) : 1; int histoYSize = histoBits > 0 ? LosslessUtils.SubSampleSize(ySize, histoBits) : 1; @@ -34,7 +34,7 @@ public static void GetHistoImageSymbols(int xSize, int ySize, Vp8LBackwardRefs r int entropyCombineNumBins = BinSize; ushort[] mapTmp = new ushort[imageHistoRawSize]; ushort[] clusterMappings = new ushort[imageHistoRawSize]; - var origHisto = new List(imageHistoRawSize); + var origHisto = new List(imageHistoRawSize); for (int i = 0; i < imageHistoRawSize; i++) { origHisto.Add(new Vp8LHistogram(cacheBits)); @@ -76,7 +76,7 @@ public static void GetHistoImageSymbols(int xSize, int ySize, Vp8LBackwardRefs r HistogramRemap(origHisto, imageHisto, histogramSymbols); } - private static void RemoveEmptyHistograms(List histograms) + private static void RemoveEmptyHistograms(List histograms) { int size = 0; for (int i = 0; i < histograms.Count; i++) @@ -95,7 +95,7 @@ private static void RemoveEmptyHistograms(List histograms) /// /// Construct the histograms from the backward references. /// - private static void HistogramBuild(int xSize, int histoBits, Vp8LBackwardRefs backwardRefs, List histograms) + private static void HistogramBuild(int xSize, int histoBits, Vp8LBackwardRefs backwardRefs, List histograms) { int x = 0, y = 0; int histoXSize = LosslessUtils.SubSampleSize(xSize, histoBits); @@ -104,7 +104,7 @@ private static void HistogramBuild(int xSize, int histoBits, Vp8LBackwardRefs ba { PixOrCopy v = backwardRefsEnumerator.Current; int ix = ((y >> histoBits) * histoXSize) + (x >> histoBits); - histograms[ix].AddSinglePixOrCopy(v, false); + histograms[ix]!.AddSinglePixOrCopy(v, false); x += v.Len; while (x >= xSize) { @@ -118,7 +118,7 @@ private static void HistogramBuild(int xSize, int histoBits, Vp8LBackwardRefs ba /// Partition histograms to different entropy bins for three dominant (literal, /// red and blue) symbol costs and compute the histogram aggregate bitCost. /// - private static void HistogramAnalyzeEntropyBin(List histograms, ushort[] binMap) + private static void HistogramAnalyzeEntropyBin(List histograms, ushort[] binMap) { int histoSize = histograms.Count; var costRange = new DominantCostRange(); @@ -131,7 +131,7 @@ private static void HistogramAnalyzeEntropyBin(List histograms, u continue; } - costRange.UpdateDominantCostRange(histograms[i]); + costRange.UpdateDominantCostRange(histograms[i]!); } // bin-hash histograms on three of the dominant (literal, red and blue) @@ -143,18 +143,18 @@ private static void HistogramAnalyzeEntropyBin(List histograms, u continue; } - binMap[i] = (ushort)costRange.GetHistoBinIndex(histograms[i], NumPartitions); + binMap[i] = (ushort)costRange.GetHistoBinIndex(histograms[i]!, NumPartitions); } } - private static int HistogramCopyAndAnalyze(List origHistograms, List histograms, ushort[] histogramSymbols) + private static int HistogramCopyAndAnalyze(List origHistograms, List histograms, ushort[] histogramSymbols) { var stats = new Vp8LStreaks(); var bitsEntropy = new Vp8LBitEntropy(); for (int clusterId = 0, i = 0; i < origHistograms.Count; i++) { - Vp8LHistogram origHistogram = origHistograms[i]; - origHistogram.UpdateHistogramCost(stats, bitsEntropy); + Vp8LHistogram? origHistogram = origHistograms[i]; + origHistogram!.UpdateHistogramCost(stats, bitsEntropy); // Skip the histogram if it is completely empty, which can happen for tiles with no information (when they are skipped because of LZ77). if (!origHistogram.IsUsed[0] && !origHistogram.IsUsed[1] && !origHistogram.IsUsed[2] && !origHistogram.IsUsed[3] && !origHistogram.IsUsed[4]) @@ -175,7 +175,7 @@ private static int HistogramCopyAndAnalyze(List origHistograms, L } private static void HistogramCombineEntropyBin( - List histograms, + List histograms, ushort[] clusters, ushort[] clusterMappings, Vp8LHistogram curCombo, @@ -215,9 +215,9 @@ private static void HistogramCombineEntropyBin( else { // Try to merge #idx into #first (both share the same binId) - double bitCost = histograms[idx].BitCost; + double bitCost = histograms[idx]!.BitCost; double bitCostThresh = -bitCost * combineCostFactor; - double currCostDiff = histograms[first].AddEval(histograms[idx], stats, bitsEntropy, bitCostThresh, curCombo); + double currCostDiff = histograms[first]!.AddEval(histograms[idx]!, stats, bitsEntropy, bitCostThresh, curCombo!); if (currCostDiff < bitCostThresh) { @@ -226,13 +226,13 @@ private static void HistogramCombineEntropyBin( // For some images, 'tryCombine' turns out to be false for a lot of // histogram pairs. In that case, we fallback to combining // histograms as usual to avoid increasing the header size. - bool tryCombine = curCombo.TrivialSymbol != NonTrivialSym || (histograms[idx].TrivialSymbol == NonTrivialSym && histograms[first].TrivialSymbol == NonTrivialSym); + bool tryCombine = curCombo!.TrivialSymbol != NonTrivialSym || (histograms[idx]!.TrivialSymbol == NonTrivialSym && histograms[first]!.TrivialSymbol == NonTrivialSym); int maxCombineFailures = 32; if (tryCombine || binInfo[binId].NumCombineFailures >= maxCombineFailures) { // Move the (better) merged histogram to its final slot. Vp8LHistogram tmp = curCombo; - curCombo = histograms[first]; + curCombo = histograms[first]!; histograms[first] = tmp; histograms[idx] = null; @@ -309,7 +309,7 @@ private static void OptimizeHistogramSymbols(ushort[] clusterMappings, int numCl /// Perform histogram aggregation using a stochastic approach. /// /// true if a greedy approach needs to be performed afterwards, false otherwise. - private static bool HistogramCombineStochastic(List histograms, int minClusterSize) + private static bool HistogramCombineStochastic(List histograms, int minClusterSize) { uint seed = 1; int triesWithNoSuccess = 0; @@ -393,8 +393,8 @@ private static bool HistogramCombineStochastic(List histograms, i src.CopyTo(dst); // Merge the histograms and remove bestIdx2 from the list. - HistogramAdd(histograms[bestIdx2], histograms[bestIdx1], histograms[bestIdx1]); - histograms.ElementAt(bestIdx1).BitCost = histoPriorityList[0].CostCombo; + HistogramAdd(histograms[bestIdx2]!, histograms[bestIdx1]!, histograms[bestIdx1]!); + histograms.ElementAt(bestIdx1)!.BitCost = histoPriorityList[0].CostCombo; histograms[bestIdx2] = null; numUsed--; @@ -438,7 +438,7 @@ private static bool HistogramCombineStochastic(List histograms, i if (doEval) { // Re-evaluate the cost of an updated pair. - HistoListUpdatePair(histograms[p.Idx1], histograms[p.Idx2], stats, bitsEntropy, 0.0d, p); + HistoListUpdatePair(histograms[p.Idx1]!, histograms[p.Idx2]!, stats, bitsEntropy, 0.0d, p); if (p.CostDiff >= 0.0d) { histoPriorityList[j] = histoPriorityList[histoPriorityList.Count - 1]; @@ -459,7 +459,7 @@ private static bool HistogramCombineStochastic(List histograms, i return doGreedy; } - private static void HistogramCombineGreedy(List histograms) + private static void HistogramCombineGreedy(List histograms) { int histoSize = histograms.Count(h => h != null); @@ -491,8 +491,8 @@ private static void HistogramCombineGreedy(List histograms) { int idx1 = histoPriorityList[0].Idx1; int idx2 = histoPriorityList[0].Idx2; - HistogramAdd(histograms[idx2], histograms[idx1], histograms[idx1]); - histograms[idx1].BitCost = histoPriorityList[0].CostCombo; + HistogramAdd(histograms[idx2]!, histograms[idx1]!, histograms[idx1]!); + histograms[idx1]!.BitCost = histoPriorityList[0].CostCombo; // Remove merged histogram. histograms[idx2] = null; @@ -527,7 +527,7 @@ private static void HistogramCombineGreedy(List histograms) } } - private static void HistogramRemap(List input, List output, ushort[] symbols) + private static void HistogramRemap(List input, List output, ushort[] symbols) { int inSize = input.Count; int outSize = output.Count; @@ -548,7 +548,7 @@ private static void HistogramRemap(List input, List input, List input, List input, List /// The cost of the pair, or 0 if it superior to threshold. - private static double HistoPriorityListPush(List histoList, int maxSize, List histograms, int idx1, int idx2, double threshold, Vp8LStreaks stats, Vp8LBitEntropy bitsEntropy) + private static double HistoPriorityListPush(List histoList, int maxSize, List histograms, int idx1, int idx2, double threshold, Vp8LStreaks stats, Vp8LBitEntropy bitsEntropy) { var pair = new HistogramPair(); @@ -609,10 +609,10 @@ private static double HistoPriorityListPush(List histoList, int m pair.Idx1 = idx1; pair.Idx2 = idx2; - Vp8LHistogram h1 = histograms[idx1]; - Vp8LHistogram h2 = histograms[idx2]; + Vp8LHistogram? h1 = histograms[idx1]; + Vp8LHistogram? h2 = histograms[idx2]; - HistoListUpdatePair(h1, h2, stats, bitsEntropy, threshold, pair); + HistoListUpdatePair(h1!, h2!, stats, bitsEntropy, threshold, pair); // Do not even consider the pair if it does not improve the entropy. if (pair.CostDiff >= threshold) diff --git a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs index 5d9c207096..68987eebf1 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs @@ -266,6 +266,7 @@ public static void ColorIndexInverseTransform(Vp8LTransform transform, Span> transform.Bits; int width = transform.XSize; int height = transform.YSize; + ArgumentNullException.ThrowIfNull(transform.Data); Span colorMap = transform.Data.GetSpan(); int decodedPixels = 0; if (bitsPerPixel < 8) @@ -328,6 +329,7 @@ public static void ColorSpaceInverseTransform(Vp8LTransform transform, Span> transform.Bits) * tilesPerRow; + ArgumentNullException.ThrowIfNull(transform.Data); Span transformData = transform.Data.GetSpan(); int pixelPos = 0; @@ -573,6 +575,7 @@ public static void PredictorInverseTransform( uint* output = outputFixed; int width = transform.XSize; + ArgumentNullException.ThrowIfNull(transform.Data); Span transformData = transform.Data.GetSpan(); // First Row follows the L (mode=1) mode. diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LDecoder.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LDecoder.cs index 80c0bb437b..885ce5645f 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LDecoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LDecoder.cs @@ -43,7 +43,7 @@ public Vp8LDecoder(int width, int height, MemoryAllocator memoryAllocator) /// /// Gets or sets the transformations which needs to be reversed. /// - public List Transforms { get; set; } + public List? Transforms { get; set; } /// /// Gets the pixel data. diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs index 3917c863b9..fe2fb5e056 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs @@ -157,7 +157,7 @@ public Vp8LEncoder( /// /// Gets or sets the scratch memory for bgra rows used for predictions. /// - public IMemoryOwner BgraScratch { get; set; } + public IMemoryOwner? BgraScratch { get; set; } /// /// Gets or sets the packed image width. @@ -177,7 +177,7 @@ public Vp8LEncoder( /// /// Gets or sets the transform data. /// - public IMemoryOwner TransformData { get; set; } + public IMemoryOwner? TransformData { get; set; } /// /// Gets or sets the cache bits. If equal to 0, don't use color cache. @@ -440,7 +440,7 @@ private void EncodeStream(Image image) private bool ConvertPixelsToBgra(Image image, int width, int height) where TPixel : unmanaged, IPixel { - Buffer2D imageBuffer = image.Frames.RootFrame.PixelBuffer; + Buffer2D imageBuffer = image.Frames.RootFrame.PixelBuffer!; bool nonOpaque = false; Span bgra = this.Bgra.GetSpan(); Span bgraBytes = MemoryMarshal.Cast(bgra); @@ -578,7 +578,7 @@ private void EncodeImage(int width, int height, bool useCache, CrunchConfig conf // two as a temporary for later usage. Vp8LBackwardRefs refsTmp = this.Refs[refsBest.Equals(this.Refs[0]) ? 1 : 0]; - this.bitWriter.Reset(bwInit); + this.bitWriter!.Reset(bwInit); Vp8LHistogram tmpHisto = new(cacheBits); List histogramImage = new(histogramImageXySize); for (int i = 0; i < histogramImageXySize; i++) @@ -587,7 +587,7 @@ private void EncodeImage(int width, int height, bool useCache, CrunchConfig conf } // Build histogram image and symbols from backward references. - HistogramEncoder.GetHistoImageSymbols(width, height, refsBest, this.quality, this.HistoBits, cacheBits, histogramImage, tmpHisto, histogramSymbols); + HistogramEncoder.GetHistoImageSymbols(width, height, refsBest, this.quality, this.HistoBits, cacheBits, histogramImage!, tmpHisto, histogramSymbols); // Create Huffman bit lengths and codes for each histogram image. int histogramImageSize = histogramImage.Count; @@ -673,14 +673,14 @@ private void EncodeImage(int width, int height, bool useCache, CrunchConfig conf if (isFirstIteration || (bitWriterBest != null && this.bitWriter.NumBytes() < bitWriterBest.NumBytes())) { Vp8LBitWriter tmp = this.bitWriter; - this.bitWriter = bitWriterBest; + this.bitWriter = bitWriterBest!; bitWriterBest = tmp; } isFirstIteration = false; } - this.bitWriter = bitWriterBest; + this.bitWriter = bitWriterBest!; } /// @@ -721,6 +721,8 @@ private void ApplyPredictFilter(int width, int height, bool lowEffort) int transformWidth = LosslessUtils.SubSampleSize(width, predBits); int transformHeight = LosslessUtils.SubSampleSize(height, predBits); + ArgumentNullException.ThrowIfNull(this.BgraScratch); + ArgumentNullException.ThrowIfNull(this.TransformData); PredictorEncoder.ResidualImage( width, height, @@ -749,6 +751,7 @@ private void ApplyCrossColorFilter(int width, int height, bool lowEffort) int transformWidth = LosslessUtils.SubSampleSize(width, colorTransformBits); int transformHeight = LosslessUtils.SubSampleSize(height, colorTransformBits); + ArgumentNullException.ThrowIfNull(this.TransformData); PredictorEncoder.ColorSpaceTransform(width, height, colorTransformBits, this.quality, this.EncodedData.GetSpan(), this.TransformData.GetSpan(), this.scratch); this.bitWriter.PutBits(WebpConstants.TransformPresent, 1); @@ -1830,9 +1833,9 @@ public void Dispose() { this.Bgra.Dispose(); this.EncodedData.Dispose(); - this.BgraScratch.Dispose(); + this.BgraScratch?.Dispose(); this.Palette.Dispose(); - this.TransformData.Dispose(); + this.TransformData?.Dispose(); this.HashChain.Dispose(); } } diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LMetadata.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LMetadata.cs index afc7d64fb7..3f0d99c0ef 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LMetadata.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LMetadata.cs @@ -9,7 +9,7 @@ internal class Vp8LMetadata { public int ColorCacheSize { get; set; } - public ColorCache ColorCache { get; set; } + public ColorCache? ColorCache { get; set; } public int HuffmanMask { get; set; } @@ -17,11 +17,11 @@ internal class Vp8LMetadata public int HuffmanXSize { get; set; } - public IMemoryOwner HuffmanImage { get; set; } + public IMemoryOwner? HuffmanImage { get; set; } public int NumHTreeGroups { get; set; } - public HTreeGroup[] HTreeGroups { get; set; } + public HTreeGroup[]? HTreeGroups { get; set; } - public HuffmanCode[] HuffmanTables { get; set; } + public HuffmanCode[]? HuffmanTables { get; set; } } diff --git a/src/ImageSharp/Formats/Webp/Lossless/Vp8LTransform.cs b/src/ImageSharp/Formats/Webp/Lossless/Vp8LTransform.cs index daf5d65a0c..90ebec1cac 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/Vp8LTransform.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/Vp8LTransform.cs @@ -42,5 +42,5 @@ public Vp8LTransform(Vp8LTransformType transformType, int xSize, int ySize) /// /// Gets or sets the transform data. /// - public IMemoryOwner Data { get; set; } + public IMemoryOwner? Data { get; set; } } diff --git a/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs b/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs index dd04b2eb9a..e93ea63c5b 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/WebpLosslessDecoder.cs @@ -102,7 +102,7 @@ public void Decode(Buffer2D pixels, int width, int height) } } - public IMemoryOwner DecodeImageStream(Vp8LDecoder decoder, int xSize, int ySize, bool isLevel0) + public IMemoryOwner? DecodeImageStream(Vp8LDecoder decoder, int xSize, int ySize, bool isLevel0) { int transformXSize = xSize; int transformYSize = ySize; @@ -212,7 +212,7 @@ public void DecodeImageData(Vp8LDecoder decoder, Span pixelData) int col = lastPixel % width; const int lenCodeLimit = WebpConstants.NumLiteralCodes + WebpConstants.NumLengthCodes; int colorCacheSize = decoder.Metadata.ColorCacheSize; - ColorCache colorCache = decoder.Metadata.ColorCache; + ColorCache? colorCache = decoder.Metadata.ColorCache; int colorCacheLimit = lenCodeLimit + colorCacheSize; int mask = decoder.Metadata.HuffmanMask; Span hTreeGroup = GetHTreeGroupForPos(decoder.Metadata, col, row); @@ -231,7 +231,7 @@ public void DecodeImageData(Vp8LDecoder decoder, Span pixelData) if (hTreeGroup[0].IsTrivialCode) { pixelData[decodedPixels] = hTreeGroup[0].LiteralArb; - AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); + AdvanceByOne(ref col, ref row, width, colorCache!, ref decodedPixels, pixelData, ref lastCached); continue; } @@ -246,7 +246,7 @@ public void DecodeImageData(Vp8LDecoder decoder, Span pixelData) if (code == PackedNonLiteralCode) { - AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); + AdvanceByOne(ref col, ref row, width, colorCache!, ref decodedPixels, pixelData, ref lastCached); continue; } } @@ -281,7 +281,7 @@ public void DecodeImageData(Vp8LDecoder decoder, Span pixelData) pixelData[decodedPixels] = (uint)(((byte)alpha << 24) | ((byte)red << 16) | ((byte)code << 8) | (byte)blue); } - AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); + AdvanceByOne(ref col, ref row, width, colorCache!, ref decodedPixels, pixelData, ref lastCached); } else if (code < lenCodeLimit) { @@ -326,11 +326,11 @@ public void DecodeImageData(Vp8LDecoder decoder, Span pixelData) int key = code - lenCodeLimit; while (lastCached < decodedPixels) { - colorCache.Insert(pixelData[lastCached]); + colorCache!.Insert(pixelData[lastCached]); lastCached++; } - pixelData[decodedPixels] = colorCache.Lookup(key); + pixelData[decodedPixels] = colorCache!.Lookup(key); AdvanceByOne(ref col, ref row, width, colorCache, ref decodedPixels, pixelData, ref lastCached); } else @@ -376,8 +376,8 @@ private void ReadHuffmanCodes(Vp8LDecoder decoder, int xSize, int ySize, int col int huffmanYSize = LosslessUtils.SubSampleSize(ySize, huffmanPrecision); int huffmanPixels = huffmanXSize * huffmanYSize; - IMemoryOwner huffmanImage = this.DecodeImageStream(decoder, huffmanXSize, huffmanYSize, false); - Span huffmanImageSpan = huffmanImage.GetSpan(); + IMemoryOwner? huffmanImage = this.DecodeImageStream(decoder, huffmanXSize, huffmanYSize, false); + Span huffmanImageSpan = huffmanImage!.GetSpan(); decoder.Metadata.HuffmanSubSampleBits = huffmanPrecision; // TODO: Isn't huffmanPixels the length of the span? @@ -393,7 +393,7 @@ private void ReadHuffmanCodes(Vp8LDecoder decoder, int xSize, int ySize, int col } numHTreeGroups = numHTreeGroupsMax; - decoder.Metadata.HuffmanImage = huffmanImage; + decoder.Metadata.HuffmanImage = huffmanImage!; } // Find maximum alphabet size for the hTree group. @@ -621,6 +621,7 @@ private void ReadTransformation(int xSize, int ySize, Vp8LDecoder decoder) Vp8LTransformType transformType = (Vp8LTransformType)this.bitReader.ReadValue(2); Vp8LTransform transform = new(transformType, xSize, ySize); + ArgumentNullException.ThrowIfNull(decoder.Transforms); // Each transform is allowed to be used only once. foreach (Vp8LTransform decoderTransform in decoder.Transforms) { @@ -656,11 +657,11 @@ private void ReadTransformation(int xSize, int ySize, Vp8LDecoder decoder) transform.Bits = 3; } - using (IMemoryOwner colorMap = this.DecodeImageStream(decoder, (int)numColors, 1, false)) + using (IMemoryOwner? colorMap = this.DecodeImageStream(decoder, (int)numColors, 1, false)) { int finalNumColors = 1 << (8 >> transform.Bits); IMemoryOwner newColorMap = this.memoryAllocator.Allocate(finalNumColors, AllocationOptions.Clean); - LosslessUtils.ExpandColorMap((int)numColors, colorMap.GetSpan(), newColorMap.GetSpan()); + LosslessUtils.ExpandColorMap((int)numColors, colorMap!.GetSpan(), newColorMap.GetSpan()); transform.Data = newColorMap; } @@ -673,7 +674,7 @@ private void ReadTransformation(int xSize, int ySize, Vp8LDecoder decoder) transform.Bits = (int)this.bitReader.ReadValue(3) + 2; int blockWidth = LosslessUtils.SubSampleSize(transform.XSize, transform.Bits); int blockHeight = LosslessUtils.SubSampleSize(transform.YSize, transform.Bits); - transform.Data = this.DecodeImageStream(decoder, blockWidth, blockHeight, false); + transform.Data = this.DecodeImageStream(decoder, blockWidth, blockHeight, false)!; break; } @@ -689,6 +690,7 @@ private void ReadTransformation(int xSize, int ySize, Vp8LDecoder decoder) /// The memory allocator is needed to allocate memory during the predictor transform. public static void ApplyInverseTransforms(Vp8LDecoder decoder, Span pixelData, MemoryAllocator memoryAllocator) { + ArgumentNullException.ThrowIfNull(decoder.Transforms); List transforms = decoder.Transforms; for (int i = transforms.Count - 1; i >= 0; i--) { @@ -903,7 +905,7 @@ private int GetCopyDistance(int distanceSymbol) [MethodImpl(InliningOptions.ShortMethod)] private static Span GetHTreeGroupForPos(Vp8LMetadata metadata, int x, int y) { - uint metaIndex = GetMetaIndex(metadata.HuffmanImage, metadata.HuffmanXSize, metadata.HuffmanSubSampleBits, x, y); + uint metaIndex = GetMetaIndex(metadata.HuffmanImage!, metadata.HuffmanXSize, metadata.HuffmanSubSampleBits, x, y); return metadata.HTreeGroups.AsSpan((int)metaIndex); } diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Decoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Decoder.cs index 8a16cb04dc..9d8a8cc1af 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Decoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Decoder.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy; /// internal class Vp8Decoder : IDisposable { - private Vp8MacroBlock leftMacroBlock; + private Vp8MacroBlock? leftMacroBlock; /// /// Initializes a new instance of the class. @@ -140,7 +140,7 @@ public Vp8Decoder(Vp8FrameHeader frameHeader, Vp8PictureHeader pictureHeader, Vp /// /// Gets or sets the top intra modes values: 4 * MbWidth. /// - public byte[] IntraT { get; set; } + public byte[]? IntraT { get; set; } /// /// Gets the left intra modes values. diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs index b15ccc052b..aa4de4aa24 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs @@ -53,7 +53,7 @@ internal class Vp8Encoder : IDisposable /// /// A bit writer for writing lossy webp streams. /// - private Vp8BitWriter bitWriter; + private Vp8BitWriter? bitWriter; private readonly Vp8RdLevel rdOptLevel; @@ -195,7 +195,7 @@ public Vp8Encoder( /// /// Gets the segment features. /// - public Vp8EncSegmentHeader SegmentHeader { get; private set; } + public Vp8EncSegmentHeader? SegmentHeader { get; private set; } /// /// Gets the segment infos. @@ -519,6 +519,8 @@ private long OneStatPass(int width, int height, int yStride, int uvStride, Vp8Rd } while (it.Next() && --nbMbs > 0); + ArgumentNullException.ThrowIfNull(this.SegmentHeader); + sizeP0 += this.SegmentHeader.Size; if (stats.DoSizeSearch) { @@ -598,6 +600,8 @@ private void ResetBoundaryPredictions() // Simplified k-Means, to assign Nb segments based on alpha-histogram. private void AssignSegments(int[] alphas) { + ArgumentNullException.ThrowIfNull(this.SegmentHeader); + int nb = this.SegmentHeader.NumSegments < NumMbSegments ? this.SegmentHeader.NumSegments : NumMbSegments; int[] centers = new int[NumMbSegments]; int weightedAverage = 0; @@ -692,6 +696,7 @@ private void AssignSegments(int[] alphas) private void SetSegmentAlphas(int[] centers, int mid) { + ArgumentNullException.ThrowIfNull(this.SegmentHeader); int nb = this.SegmentHeader.NumSegments; Vp8SegmentInfo[] dqm = this.SegmentInfos; int min = centers[0], max = centers[0]; @@ -729,6 +734,7 @@ private void SetSegmentAlphas(int[] centers, int mid) private void SetSegmentParams(float quality) { + ArgumentNullException.ThrowIfNull(this.SegmentHeader); int nb = this.SegmentHeader.NumSegments; Vp8SegmentInfo[] dqm = this.SegmentInfos; double amp = WebpConstants.SnsToDq * this.spatialNoiseShaping / 100.0d / 128.0d; @@ -820,6 +826,7 @@ private void SetSegmentProbas() ++p[mb.Segment]; } + ArgumentNullException.ThrowIfNull(this.SegmentHeader); if (this.SegmentHeader.NumSegments > 1) { byte[] probas = this.Proba.Segments; @@ -998,6 +1005,7 @@ private void CodeResiduals(Vp8EncIterator it, Vp8ModeScore rd, Vp8Residual resid it.NzToBytes(); + ArgumentNullException.ThrowIfNull(this.bitWriter); int pos1 = this.bitWriter.NumBytes(); if (i16) { diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs index a6c3879bb7..b4fc667af7 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Residual.cs @@ -26,11 +26,11 @@ internal class Vp8Residual public short[] Coeffs { get; } = new short[16]; - public Vp8BandProbas[] Prob { get; set; } + public Vp8BandProbas[]? Prob { get; set; } - public Vp8Stats[] Stats { get; set; } + public Vp8Stats[]? Stats { get; set; } - public Vp8Costs[] Costs { get; set; } + public Vp8Costs[]? Costs { get; set; } public void Init(int first, int coeffType, Vp8EncProba prob) { @@ -86,7 +86,7 @@ public void SetCoeffs(Span coeffs) public int RecordCoeffs(int ctx) { int n = this.First; - Vp8StatsArray s = this.Stats[n].Stats[ctx]; + Vp8StatsArray s = this.Stats![n].Stats[ctx]; if (this.Last < 0) { RecordStats(0, s, 0); @@ -145,9 +145,9 @@ public int RecordCoeffs(int ctx) public int GetResidualCost(int ctx0) { int n = this.First; - int p0 = this.Prob[n].Probabilities[ctx0].Probabilities[0]; - Vp8Costs[] costs = this.Costs; - Vp8CostArray t = costs[n].Costs[ctx0]; + int p0 = this.Prob![n].Probabilities[ctx0].Probabilities[0]; + Vp8Costs[]? costs = this.Costs; + Vp8CostArray t = costs![n].Costs[ctx0]; // bitCost(1, p0) is already incorporated in t[] tables, but only if ctx != 0 // (as required by the syntax). For ctx0 == 0, we need to add it here or it'll diff --git a/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs b/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs index 95c97c45b3..5aec162915 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs @@ -65,7 +65,7 @@ public WebpLossyDecoder(Vp8BitReader bitReader, MemoryAllocator memoryAllocator, /// The height of the image. /// Information about the image. /// The ALPH chunk data. - public void Decode(Buffer2D pixels, int width, int height, WebpImageInfo info, IMemoryOwner alphaData) + public void Decode(Buffer2D pixels, int width, int height, WebpImageInfo info, IMemoryOwner? alphaData) where TPixel : unmanaged, IPixel { // Paragraph 9.2: color space and clamp type follow. @@ -85,7 +85,7 @@ public void Decode(Buffer2D pixels, int width, int height, WebpI Vp8Proba proba = new(); Vp8SegmentHeader vp8SegmentHeader = this.ParseSegmentHeader(proba); - using (Vp8Decoder decoder = new(info.Vp8FrameHeader, pictureHeader, vp8SegmentHeader, proba, this.memoryAllocator)) + using (Vp8Decoder decoder = new(info.Vp8FrameHeader!, pictureHeader, vp8SegmentHeader, proba, this.memoryAllocator)) { Vp8Io io = InitializeVp8Io(decoder, pictureHeader); @@ -110,6 +110,8 @@ public void Decode(Buffer2D pixels, int width, int height, WebpI if (info.Features?.Alpha == true) { + ArgumentNullException.ThrowIfNull(alphaData); + using (AlphaDecoder alphaDecoder = new( width, height, @@ -1035,7 +1037,7 @@ private static int GetLargeValue(Vp8BitReader br, byte[] p) int bit0 = br.GetBit(p[9 + bit1]); int cat = (2 * bit1) + bit0; v = 0; - byte[] tab = null; + byte[]? tab = null; switch (cat) { case 0: @@ -1055,7 +1057,7 @@ private static int GetLargeValue(Vp8BitReader br, byte[] p) break; } - for (int i = 0; i < tab.Length; i++) + for (int i = 0; i < tab!.Length; i++) { v += v + br.GetBit(tab[i]); } @@ -1156,7 +1158,7 @@ private void ParsePartitions(Vp8Decoder dec) { uint size = this.bitReader.Remaining - this.bitReader.PartitionLength; int startIdx = (int)this.bitReader.PartitionLength; - Span sz = this.bitReader.Data.Slice(startIdx); + Span sz = this.bitReader.Data!.Slice(startIdx); int sizeLeft = (int)size; dec.NumPartsMinusOne = (1 << (int)this.bitReader.ReadValue(2)) - 1; int lastPart = dec.NumPartsMinusOne; @@ -1172,13 +1174,13 @@ private void ParsePartitions(Vp8Decoder dec) pSize = sizeLeft; } - dec.Vp8BitReaders[p] = new Vp8BitReader(this.bitReader.Data, (uint)pSize, partStart); + dec.Vp8BitReaders[p] = new Vp8BitReader(this.bitReader.Data!, (uint)pSize, partStart); partStart += pSize; sizeLeft -= pSize; sz = sz[3..]; } - dec.Vp8BitReaders[lastPart] = new Vp8BitReader(this.bitReader.Data, (uint)sizeLeft, partStart); + dec.Vp8BitReaders[lastPart] = new Vp8BitReader(this.bitReader.Data!, (uint)sizeLeft, partStart); } private void ParseDequantizationIndices(Vp8Decoder decoder) diff --git a/src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs b/src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs index 5c6dde6224..fe07c0aa16 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/YuvConversion.cs @@ -272,7 +272,7 @@ private static void PackAndStore(Vector128 a, Vector128 b, Vector128 public static bool ConvertRgbToYuv(Image image, Configuration configuration, MemoryAllocator memoryAllocator, Span y, Span u, Span v) where TPixel : unmanaged, IPixel { - Buffer2D imageBuffer = image.Frames.RootFrame.PixelBuffer; + Buffer2D imageBuffer = image.Frames.RootFrame.PixelBuffer!; int width = imageBuffer.Width; int height = imageBuffer.Height; int uvWidth = (width + 1) >> 1; diff --git a/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs b/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs index 6c45e26614..7f1ab1807f 100644 --- a/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs +++ b/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs @@ -45,17 +45,17 @@ internal class WebpAnimationDecoder : IDisposable /// /// The abstract metadata. /// - private ImageMetadata metadata; + private ImageMetadata? metadata; /// /// The gif specific metadata. /// - private WebpMetadata webpMetadata; + private WebpMetadata? webpMetadata; /// /// The alpha data, if an ALPH chunk is present. /// - private IMemoryOwner alphaData; + private IMemoryOwner? alphaData; /// /// Initializes a new instance of the class. @@ -82,8 +82,8 @@ public WebpAnimationDecoder(MemoryAllocator memoryAllocator, Configuration confi public Image Decode(BufferedReadStream stream, WebpFeatures features, uint width, uint height, uint completeDataSize) where TPixel : unmanaged, IPixel { - Image image = null; - ImageFrame previousFrame = null; + Image? image = null; + ImageFrame? previousFrame = null; this.metadata = new ImageMetadata(); this.webpMetadata = this.metadata.GetWebpMetadata(); @@ -98,12 +98,12 @@ public Image Decode(BufferedReadStream stream, WebpFeatures feat switch (chunkType) { case WebpChunkType.Animation: - uint dataSize = this.ReadFrame(stream, ref image, ref previousFrame, width, height, features.AnimationBackgroundColor.Value); + uint dataSize = this.ReadFrame(stream, ref image, ref previousFrame, width, height, features.AnimationBackgroundColor!.Value); remainingBytes -= (int)dataSize; break; case WebpChunkType.Xmp: case WebpChunkType.Exif: - WebpChunkParsingUtils.ParseOptionalChunks(stream, chunkType, image.Metadata, false, this.buffer); + WebpChunkParsingUtils.ParseOptionalChunks(stream, chunkType, image!.Metadata, false, this.buffer); break; default: WebpThrowHelper.ThrowImageFormatException("Read unexpected webp chunk data"); @@ -116,7 +116,7 @@ public Image Decode(BufferedReadStream stream, WebpFeatures feat } } - return image; + return image!; } /// @@ -129,7 +129,7 @@ public Image Decode(BufferedReadStream stream, WebpFeatures feat /// The width of the image. /// The height of the image. /// The default background color of the canvas in. - private uint ReadFrame(BufferedReadStream stream, ref Image image, ref ImageFrame previousFrame, uint width, uint height, Color backgroundColor) + private uint ReadFrame(BufferedReadStream stream, ref Image? image, ref ImageFrame? previousFrame, uint width, uint height, Color backgroundColor) where TPixel : unmanaged, IPixel { AnimationFrameData frameData = this.ReadFrameHeader(stream); @@ -145,7 +145,7 @@ private uint ReadFrame(BufferedReadStream stream, ref Image imag chunkType = WebpChunkParsingUtils.ReadChunkType(stream, this.buffer); } - WebpImageInfo webpInfo = null; + WebpImageInfo? webpInfo = null; WebpFeatures features = new(); switch (chunkType) { @@ -162,10 +162,11 @@ private uint ReadFrame(BufferedReadStream stream, ref Image imag break; } - ImageFrame currentFrame = null; + ImageFrame? currentFrame = null; ImageFrame imageFrame; if (previousFrame is null) { + ArgumentNullException.ThrowIfNull(this.metadata); image = new Image(this.configuration, (int)width, (int)height, backgroundColor.ToPixel(), this.metadata); SetFrameMetadata(image.Frames.RootFrame.Metadata, frameData.Duration); @@ -174,7 +175,7 @@ private uint ReadFrame(BufferedReadStream stream, ref Image imag } else { - currentFrame = image.Frames.AddFrame(previousFrame); // This clones the frame and adds it the collection. + currentFrame = image!.Frames.AddFrame(previousFrame); // This clones the frame and adds it the collection. SetFrameMetadata(currentFrame.Metadata, frameData.Duration); @@ -244,22 +245,22 @@ private byte ReadAlphaData(BufferedReadStream stream) /// The frame data. /// The webp information. /// A decoded image. - private Buffer2D DecodeImageData(AnimationFrameData frameData, WebpImageInfo webpInfo) + private Buffer2D DecodeImageData(AnimationFrameData frameData, WebpImageInfo? webpInfo) where TPixel : unmanaged, IPixel { Image decodedImage = new((int)frameData.Width, (int)frameData.Height); try { - Buffer2D pixelBufferDecoded = decodedImage.Frames.RootFrame.PixelBuffer; - if (webpInfo.IsLossless) + Buffer2D pixelBufferDecoded = decodedImage.Frames.RootFrame.PixelBuffer!; + if (webpInfo!.IsLossless) { - WebpLosslessDecoder losslessDecoder = new(webpInfo.Vp8LBitReader, this.memoryAllocator, this.configuration); + WebpLosslessDecoder losslessDecoder = new(webpInfo.Vp8LBitReader!, this.memoryAllocator, this.configuration); losslessDecoder.Decode(pixelBufferDecoded, (int)webpInfo.Width, (int)webpInfo.Height); } else { - WebpLossyDecoder lossyDecoder = new(webpInfo.Vp8BitReader, this.memoryAllocator, this.configuration); + WebpLossyDecoder lossyDecoder = new(webpInfo.Vp8BitReader!, this.memoryAllocator, this.configuration); lossyDecoder.Decode(pixelBufferDecoded, (int)webpInfo.Width, (int)webpInfo.Height, webpInfo, this.alphaData); } @@ -272,7 +273,7 @@ private Buffer2D DecodeImageData(AnimationFrameData frameData, W } finally { - webpInfo.Dispose(); + webpInfo?.Dispose(); } } @@ -289,7 +290,7 @@ private Buffer2D DecodeImageData(AnimationFrameData frameData, W private static void DrawDecodedImageOnCanvas(Buffer2D decodedImage, ImageFrame imageFrame, int frameX, int frameY, int frameWidth, int frameHeight) where TPixel : unmanaged, IPixel { - Buffer2D imageFramePixels = imageFrame.PixelBuffer; + Buffer2D imageFramePixels = imageFrame.PixelBuffer!; int decodedRowIdx = 0; for (int y = frameY; y < frameY + frameHeight; y++) { @@ -313,8 +314,8 @@ private static void DrawDecodedImageOnCanvas(Buffer2D decodedIma private void AlphaBlend(ImageFrame src, ImageFrame dst, int frameX, int frameY, int frameWidth, int frameHeight) where TPixel : unmanaged, IPixel { - Buffer2D srcPixels = src.PixelBuffer; - Buffer2D dstPixels = dst.PixelBuffer; + Buffer2D srcPixels = src.PixelBuffer!; + Buffer2D dstPixels = dst.PixelBuffer!; PixelBlender blender = PixelOperations.Instance.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.SrcOver); for (int y = frameY; y < frameY + frameHeight; y++) { @@ -341,7 +342,7 @@ private void RestoreToBackground(ImageFrame imageFrame, Color ba } Rectangle interest = Rectangle.Intersect(imageFrame.Bounds(), this.restoreArea.Value); - Buffer2DRegion pixelRegion = imageFrame.PixelBuffer.GetRegion(interest); + Buffer2DRegion pixelRegion = imageFrame.PixelBuffer!.GetRegion(interest); TPixel backgroundPixel = backgroundColor.ToPixel(); pixelRegion.Fill(backgroundPixel); } diff --git a/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs b/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs index 4632200f4b..0c7287fe66 100644 --- a/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs +++ b/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs @@ -43,32 +43,27 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// /// Gets the decoded by this decoder instance. /// - private ImageMetadata metadata; + private ImageMetadata? metadata; /// /// Gets or sets the alpha data, if an ALPH chunk is present. /// - private IMemoryOwner alphaData; + private IMemoryOwner? alphaData; /// /// Used for allocating memory during the decoding operations. /// private readonly MemoryAllocator memoryAllocator; - /// - /// The stream to decode from. - /// - private BufferedReadStream currentStream; - /// /// The webp specific metadata. /// - private WebpMetadata webpMetadata; + private WebpMetadata? webpMetadata; /// /// Information about the webp image. /// - private WebpImageInfo webImageInfo; + private WebpImageInfo? webImageInfo; /// /// Initializes a new instance of the class. @@ -87,21 +82,27 @@ public WebpDecoderCore(DecoderOptions options) public DecoderOptions Options { get; } /// - public Size Dimensions => new((int)this.webImageInfo.Width, (int)this.webImageInfo.Height); + public Size? Dimensions + { + get + { + ArgumentNullException.ThrowIfNull(this.webImageInfo); + return new((int)this.webImageInfo.Width, (int)this.webImageInfo.Height); + } + } /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { - Image image = null; + Image? image = null; try { this.metadata = new ImageMetadata(); - this.currentStream = stream; - uint fileSize = this.ReadImageHeader(); + uint fileSize = this.ReadImageHeader(stream); - using (this.webImageInfo = this.ReadVp8Info()) + using (this.webImageInfo = this.ReadVp8Info(stream)) { if (this.webImageInfo.Features is { Animation: true }) { @@ -118,19 +119,19 @@ public Image Decode(BufferedReadStream stream, CancellationToken Buffer2D pixels = image.GetRootFramePixelBuffer(); if (this.webImageInfo.IsLossless) { - var losslessDecoder = new WebpLosslessDecoder(this.webImageInfo.Vp8LBitReader, this.memoryAllocator, this.configuration); + var losslessDecoder = new WebpLosslessDecoder(this.webImageInfo.Vp8LBitReader!, this.memoryAllocator, this.configuration); losslessDecoder.Decode(pixels, image.Width, image.Height); } else { - var lossyDecoder = new WebpLossyDecoder(this.webImageInfo.Vp8BitReader, this.memoryAllocator, this.configuration); + var lossyDecoder = new WebpLossyDecoder(this.webImageInfo.Vp8BitReader!, this.memoryAllocator, this.configuration); lossyDecoder.Decode(pixels, image.Width, image.Height, this.webImageInfo, this.alphaData); } // There can be optional chunks after the image data, like EXIF and XMP. if (this.webImageInfo.Features != null) { - this.ParseOptionalChunks(this.webImageInfo.Features); + this.ParseOptionalChunks(stream, this.webImageInfo.Features); } return image; @@ -146,11 +147,10 @@ public Image Decode(BufferedReadStream stream, CancellationToken /// public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { - this.currentStream = stream; - - this.ReadImageHeader(); - using (this.webImageInfo = this.ReadVp8Info(true)) + this.ReadImageHeader(stream); + using (this.webImageInfo = this.ReadVp8Info(stream, true)) { + ArgumentNullException.ThrowIfNull(this.metadata); return new ImageInfo(new PixelTypeInfo((int)this.webImageInfo.BitsPerPixel), (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.metadata); } } @@ -159,18 +159,18 @@ public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancella /// Reads and skips over the image header. /// /// The file size in bytes. - private uint ReadImageHeader() + private uint ReadImageHeader(BufferedReadStream stream) { // Skip FourCC header, we already know its a RIFF file at this point. - this.currentStream.Skip(4); + stream.Skip(4); // Read file size. // The size of the file in bytes starting at offset 8. // The file size in the header is the total size of the chunks that follow plus 4 bytes for the ‘WEBP’ FourCC. - uint fileSize = WebpChunkParsingUtils.ReadChunkSize(this.currentStream, this.buffer); + uint fileSize = WebpChunkParsingUtils.ReadChunkSize(stream, this.buffer); // Skip 'WEBP' from the header. - this.currentStream.Skip(4); + stream.Skip(4); return fileSize; } @@ -180,40 +180,40 @@ private uint ReadImageHeader() /// /// For identify, the alpha data should not be read. /// Information about the webp image. - private WebpImageInfo ReadVp8Info(bool ignoreAlpha = false) + private WebpImageInfo ReadVp8Info(BufferedReadStream stream, bool ignoreAlpha = false) { this.metadata = new ImageMetadata(); this.webpMetadata = this.metadata.GetFormatMetadata(WebpFormat.Instance); - WebpChunkType chunkType = WebpChunkParsingUtils.ReadChunkType(this.currentStream, this.buffer); + WebpChunkType chunkType = WebpChunkParsingUtils.ReadChunkType(stream, this.buffer); var features = new WebpFeatures(); switch (chunkType) { case WebpChunkType.Vp8: this.webpMetadata.FileFormat = WebpFileFormatType.Lossy; - return WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, this.currentStream, this.buffer, features); + return WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, stream, this.buffer, features); case WebpChunkType.Vp8L: this.webpMetadata.FileFormat = WebpFileFormatType.Lossless; - return WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, this.currentStream, this.buffer, features); + return WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, stream, this.buffer, features); case WebpChunkType.Vp8X: - WebpImageInfo webpInfos = WebpChunkParsingUtils.ReadVp8XHeader(this.currentStream, this.buffer, features); - while (this.currentStream.Position < this.currentStream.Length) + WebpImageInfo webpInfos = WebpChunkParsingUtils.ReadVp8XHeader(stream, this.buffer, features); + while (stream.Position < stream.Length) { - chunkType = WebpChunkParsingUtils.ReadChunkType(this.currentStream, this.buffer); + chunkType = WebpChunkParsingUtils.ReadChunkType(stream, this.buffer); if (chunkType == WebpChunkType.Vp8) { this.webpMetadata.FileFormat = WebpFileFormatType.Lossy; - webpInfos = WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, this.currentStream, this.buffer, features); + webpInfos = WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, stream, this.buffer, features); } else if (chunkType == WebpChunkType.Vp8L) { this.webpMetadata.FileFormat = WebpFileFormatType.Lossless; - webpInfos = WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, this.currentStream, this.buffer, features); + webpInfos = WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, stream, this.buffer, features); } else if (WebpChunkParsingUtils.IsOptionalVp8XChunk(chunkType)) { - bool isAnimationChunk = this.ParseOptionalExtendedChunks(chunkType, features, ignoreAlpha); + bool isAnimationChunk = this.ParseOptionalExtendedChunks(stream, chunkType, features, ignoreAlpha); if (isAnimationChunk) { return webpInfos; @@ -240,28 +240,28 @@ private WebpImageInfo ReadVp8Info(bool ignoreAlpha = false) /// The webp image features. /// For identify, the alpha data should not be read. /// true, if its a alpha chunk. - private bool ParseOptionalExtendedChunks(WebpChunkType chunkType, WebpFeatures features, bool ignoreAlpha) + private bool ParseOptionalExtendedChunks(BufferedReadStream stream, WebpChunkType chunkType, WebpFeatures features, bool ignoreAlpha) { switch (chunkType) { case WebpChunkType.Iccp: - this.ReadIccProfile(); + this.ReadIccProfile(stream); break; case WebpChunkType.Exif: - this.ReadExifProfile(); + this.ReadExifProfile(stream); break; case WebpChunkType.Xmp: - this.ReadXmpProfile(); + this.ReadXmpProfile(stream); break; case WebpChunkType.AnimationParameter: - this.ReadAnimationParameters(features); + this.ReadAnimationParameters(stream, features); return true; case WebpChunkType.Alpha: - this.ReadAlphaData(features, ignoreAlpha); + this.ReadAlphaData(stream, features, ignoreAlpha); break; default: WebpThrowHelper.ThrowImageFormatException("Unexpected chunk followed VP8X header"); @@ -275,31 +275,32 @@ private bool ParseOptionalExtendedChunks(WebpChunkType chunkType, WebpFeatures f /// Reads the optional metadata EXIF of XMP profiles, which can follow the image data. /// /// The webp features. - private void ParseOptionalChunks(WebpFeatures features) + private void ParseOptionalChunks(BufferedReadStream stream, WebpFeatures features) { if (this.skipMetadata || (!features.ExifProfile && !features.XmpMetaData)) { return; } - long streamLength = this.currentStream.Length; - while (this.currentStream.Position < streamLength) + long streamLength = stream.Length; + while (stream.Position < streamLength) { // Read chunk header. - WebpChunkType chunkType = this.ReadChunkType(); + WebpChunkType chunkType = this.ReadChunkType(stream); + ArgumentNullException.ThrowIfNull(this.metadata); if (chunkType == WebpChunkType.Exif && this.metadata.ExifProfile == null) { - this.ReadExifProfile(); + this.ReadExifProfile(stream); } else if (chunkType == WebpChunkType.Xmp && this.metadata.XmpProfile == null) { - this.ReadXmpProfile(); + this.ReadXmpProfile(stream); } else { // Skip duplicate XMP or EXIF chunk. - uint chunkLength = this.ReadChunkSize(); - this.currentStream.Skip((int)chunkLength); + uint chunkLength = this.ReadChunkSize(stream); + stream.Skip((int)chunkLength); } } } @@ -307,17 +308,17 @@ private void ParseOptionalChunks(WebpFeatures features) /// /// Reads the EXIF profile from the stream. /// - private void ReadExifProfile() + private void ReadExifProfile(BufferedReadStream stream) { - uint exifChunkSize = this.ReadChunkSize(); + uint exifChunkSize = this.ReadChunkSize(stream); if (this.skipMetadata) { - this.currentStream.Skip((int)exifChunkSize); + stream.Skip((int)exifChunkSize); } else { byte[] exifData = new byte[exifChunkSize]; - int bytesRead = this.currentStream.Read(exifData, 0, (int)exifChunkSize); + int bytesRead = stream.Read(exifData, 0, (int)exifChunkSize); if (bytesRead != exifChunkSize) { // Ignore invalid chunk. @@ -325,6 +326,7 @@ private void ReadExifProfile() } var profile = new ExifProfile(exifData); + ArgumentNullException.ThrowIfNull(this.metadata); this.metadata.ExifProfile = profile; } } @@ -332,17 +334,17 @@ private void ReadExifProfile() /// /// Reads the XMP profile the stream. /// - private void ReadXmpProfile() + private void ReadXmpProfile(BufferedReadStream stream) { - uint xmpChunkSize = this.ReadChunkSize(); + uint xmpChunkSize = this.ReadChunkSize(stream); if (this.skipMetadata) { - this.currentStream.Skip((int)xmpChunkSize); + stream.Skip((int)xmpChunkSize); } else { byte[] xmpData = new byte[xmpChunkSize]; - int bytesRead = this.currentStream.Read(xmpData, 0, (int)xmpChunkSize); + int bytesRead = stream.Read(xmpData, 0, (int)xmpChunkSize); if (bytesRead != xmpChunkSize) { // Ignore invalid chunk. @@ -350,6 +352,7 @@ private void ReadXmpProfile() } var profile = new XmpProfile(xmpData); + ArgumentNullException.ThrowIfNull(this.metadata); this.metadata.XmpProfile = profile; } } @@ -357,17 +360,17 @@ private void ReadXmpProfile() /// /// Reads the ICCP chunk from the stream. /// - private void ReadIccProfile() + private void ReadIccProfile(BufferedReadStream stream) { - uint iccpChunkSize = this.ReadChunkSize(); + uint iccpChunkSize = this.ReadChunkSize(stream); if (this.skipMetadata) { - this.currentStream.Skip((int)iccpChunkSize); + stream.Skip((int)iccpChunkSize); } else { byte[] iccpData = new byte[iccpChunkSize]; - int bytesRead = this.currentStream.Read(iccpData, 0, (int)iccpChunkSize); + int bytesRead = stream.Read(iccpData, 0, (int)iccpChunkSize); if (bytesRead != iccpChunkSize) { WebpThrowHelper.ThrowInvalidImageContentException("Not enough data to read the iccp chunk"); @@ -376,6 +379,7 @@ private void ReadIccProfile() var profile = new IccProfile(iccpData); if (profile.CheckIsValid()) { + ArgumentNullException.ThrowIfNull(this.metadata); this.metadata.IccProfile = profile; } } @@ -385,16 +389,16 @@ private void ReadIccProfile() /// Reads the animation parameters chunk from the stream. /// /// The webp features. - private void ReadAnimationParameters(WebpFeatures features) + private void ReadAnimationParameters(BufferedReadStream stream, WebpFeatures features) { features.Animation = true; - uint animationChunkSize = WebpChunkParsingUtils.ReadChunkSize(this.currentStream, this.buffer); - byte blue = (byte)this.currentStream.ReadByte(); - byte green = (byte)this.currentStream.ReadByte(); - byte red = (byte)this.currentStream.ReadByte(); - byte alpha = (byte)this.currentStream.ReadByte(); + uint animationChunkSize = WebpChunkParsingUtils.ReadChunkSize(stream, this.buffer); + byte blue = (byte)stream.ReadByte(); + byte green = (byte)stream.ReadByte(); + byte red = (byte)stream.ReadByte(); + byte alpha = (byte)stream.ReadByte(); features.AnimationBackgroundColor = new Color(new Rgba32(red, green, blue, alpha)); - int bytesRead = this.currentStream.Read(this.buffer, 0, 2); + int bytesRead = stream.Read(this.buffer, 0, 2); if (bytesRead != 2) { WebpThrowHelper.ThrowInvalidImageContentException("Not enough data to read the animation loop count"); @@ -408,20 +412,20 @@ private void ReadAnimationParameters(WebpFeatures features) /// /// The features. /// if set to true, skips the chunk data. - private void ReadAlphaData(WebpFeatures features, bool ignoreAlpha) + private void ReadAlphaData(BufferedReadStream stream, WebpFeatures features, bool ignoreAlpha) { - uint alphaChunkSize = WebpChunkParsingUtils.ReadChunkSize(this.currentStream, this.buffer); + uint alphaChunkSize = WebpChunkParsingUtils.ReadChunkSize(stream, this.buffer); if (ignoreAlpha) { - this.currentStream.Skip((int)alphaChunkSize); + stream.Skip((int)alphaChunkSize); return; } - features.AlphaChunkHeader = (byte)this.currentStream.ReadByte(); + features.AlphaChunkHeader = (byte)stream.ReadByte(); int alphaDataSize = (int)(alphaChunkSize - 1); this.alphaData = this.memoryAllocator.Allocate(alphaDataSize); Span alphaData = this.alphaData.GetSpan(); - int bytesRead = this.currentStream.Read(alphaData, 0, alphaDataSize); + int bytesRead = stream.Read(alphaData, 0, alphaDataSize); if (bytesRead != alphaDataSize) { WebpThrowHelper.ThrowInvalidImageContentException("Not enough data to read the alpha data from the stream"); @@ -434,9 +438,9 @@ private void ReadAlphaData(WebpFeatures features, bool ignoreAlpha) /// /// Thrown if the input stream is not valid. /// - private WebpChunkType ReadChunkType() + private WebpChunkType ReadChunkType(BufferedReadStream stream) { - if (this.currentStream.Read(this.buffer, 0, 4) == 4) + if (stream.Read(this.buffer, 0, 4) == 4) { var chunkType = (WebpChunkType)BinaryPrimitives.ReadUInt32BigEndian(this.buffer); return chunkType; @@ -450,9 +454,9 @@ private WebpChunkType ReadChunkType() /// so the chunk size will be increased by 1 in those cases. /// /// The chunk size in bytes. - private uint ReadChunkSize() + private uint ReadChunkSize(BufferedReadStream stream) { - if (this.currentStream.Read(this.buffer, 0, 4) == 4) + if (stream.Read(this.buffer, 0, 4) == 4) { uint chunkSize = BinaryPrimitives.ReadUInt32LittleEndian(this.buffer); return (chunkSize % 2 == 0) ? chunkSize : chunkSize + 1; diff --git a/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs b/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs index f9ceaf3098..aa99ca11f8 100644 --- a/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs +++ b/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs @@ -75,7 +75,7 @@ internal sealed class WebpEncoderCore : IImageEncoderInternals /// /// The global configuration. /// - private Configuration configuration; + private Configuration? configuration; /// /// Initializes a new instance of the class. diff --git a/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs b/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs index 50820fd61c..3b30a2cfb5 100644 --- a/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs +++ b/src/ImageSharp/Formats/Webp/WebpImageFormatDetector.cs @@ -12,7 +12,7 @@ public sealed class WebpImageFormatDetector : IImageFormatDetector public int HeaderSize => 12; /// - public IImageFormat DetectFormat(ReadOnlySpan header) + public IImageFormat? DetectFormat(ReadOnlySpan header) => this.IsSupportedFileFormat(header) ? WebpFormat.Instance : null; private bool IsSupportedFileFormat(ReadOnlySpan header) diff --git a/src/ImageSharp/Formats/Webp/WebpImageInfo.cs b/src/ImageSharp/Formats/Webp/WebpImageInfo.cs index 2f420f453e..5f7301b262 100644 --- a/src/ImageSharp/Formats/Webp/WebpImageInfo.cs +++ b/src/ImageSharp/Formats/Webp/WebpImageInfo.cs @@ -35,7 +35,7 @@ internal class WebpImageInfo : IDisposable /// /// Gets or sets additional features present in a VP8X image. /// - public WebpFeatures Features { get; set; } + public WebpFeatures? Features { get; set; } /// /// Gets or sets the VP8 profile / version. Valid values are between 0 and 3. Default value will be the invalid value -1. @@ -45,17 +45,17 @@ internal class WebpImageInfo : IDisposable /// /// Gets or sets the VP8 frame header. /// - public Vp8FrameHeader Vp8FrameHeader { get; set; } + public Vp8FrameHeader? Vp8FrameHeader { get; set; } /// /// Gets or sets the VP8L bitreader. Will be , if its not a lossless image. /// - public Vp8LBitReader Vp8LBitReader { get; set; } + public Vp8LBitReader? Vp8LBitReader { get; set; } /// /// Gets or sets the VP8 bitreader. Will be , if its not a lossy image. /// - public Vp8BitReader Vp8BitReader { get; set; } + public Vp8BitReader? Vp8BitReader { get; set; } /// public void Dispose() diff --git a/src/ImageSharp/IO/ChunkedMemoryStream.cs b/src/ImageSharp/IO/ChunkedMemoryStream.cs index ecb299ca31..85dffd7adf 100644 --- a/src/ImageSharp/IO/ChunkedMemoryStream.cs +++ b/src/ImageSharp/IO/ChunkedMemoryStream.cs @@ -18,7 +18,7 @@ internal sealed class ChunkedMemoryStream : Stream private readonly MemoryAllocator allocator; // Data - private MemoryChunk memoryChunk; + private MemoryChunk? memoryChunk; // The total number of allocated chunks private int chunkCount; @@ -30,13 +30,13 @@ internal sealed class ChunkedMemoryStream : Stream private bool isDisposed; // Current chunk to write to - private MemoryChunk writeChunk; + private MemoryChunk? writeChunk; // Offset into chunk to write to private int writeOffset; // Current chunk to read from - private MemoryChunk readChunk; + private MemoryChunk? readChunk; // Offset into chunk to read from private int readOffset; @@ -69,10 +69,10 @@ public override long Length this.EnsureNotDisposed(); int length = 0; - MemoryChunk chunk = this.memoryChunk; + MemoryChunk? chunk = this.memoryChunk; while (chunk != null) { - MemoryChunk next = chunk.Next; + MemoryChunk? next = chunk.Next; if (next != null) { length += chunk.Length; @@ -102,11 +102,11 @@ public override long Position } int pos = 0; - MemoryChunk chunk = this.memoryChunk; + MemoryChunk? chunk = this.memoryChunk; while (chunk != this.readChunk) { - pos += chunk.Length; - chunk = chunk.Next; + pos += chunk!.Length; + chunk = chunk.Next!; } pos += this.readOffset; @@ -124,14 +124,14 @@ public override long Position } // Back up current position in case new position is out of range - MemoryChunk backupReadChunk = this.readChunk; + MemoryChunk? backupReadChunk = this.readChunk; int backupReadOffset = this.readOffset; this.readChunk = null; this.readOffset = 0; int leftUntilAtPos = (int)value; - MemoryChunk chunk = this.memoryChunk; + MemoryChunk? chunk = this.memoryChunk; while (chunk != null) { if ((leftUntilAtPos < chunk.Length) @@ -253,7 +253,7 @@ private int ReadImpl(Span buffer) this.readOffset = 0; } - IMemoryOwner chunkBuffer = this.readChunk.Buffer; + IMemoryOwner? chunkBuffer = this.readChunk.Buffer; int chunkSize = this.readChunk.Length; if (this.readChunk.Next is null) { @@ -284,7 +284,7 @@ private int ReadImpl(Span buffer) } int readCount = Math.Min(count, chunkSize - this.readOffset); - chunkBuffer.Slice(this.readOffset, readCount).CopyTo(buffer[offset..]); + chunkBuffer!.Slice(this.readOffset, readCount).CopyTo(buffer[offset..]); offset += readCount; count -= readCount; this.readOffset += readCount; @@ -311,7 +311,7 @@ public override int ReadByte() this.readOffset = 0; } - IMemoryOwner chunkBuffer = this.readChunk.Buffer; + IMemoryOwner? chunkBuffer = this.readChunk.Buffer; int chunkSize = this.readChunk.Length; if (this.readChunk.Next is null) { @@ -331,7 +331,7 @@ public override int ReadByte() chunkBuffer = this.readChunk.Buffer; } - return chunkBuffer.GetSpan()[this.readOffset++]; + return chunkBuffer!.GetSpan()[this.readOffset++]; } /// @@ -363,7 +363,7 @@ private void WriteImpl(ReadOnlySpan buffer) this.writeOffset = 0; } - Span chunkBuffer = this.writeChunk.Buffer.GetSpan(); + Span chunkBuffer = this.writeChunk!.Buffer!.GetSpan(); int chunkSize = this.writeChunk.Length; int count = buffer.Length; int offset = 0; @@ -375,7 +375,7 @@ private void WriteImpl(ReadOnlySpan buffer) this.writeChunk.Next = this.AllocateMemoryChunk(); this.writeChunk = this.writeChunk.Next; this.writeOffset = 0; - chunkBuffer = this.writeChunk.Buffer.GetSpan(); + chunkBuffer = this.writeChunk.Buffer!.GetSpan(); chunkSize = this.writeChunk.Length; } @@ -400,8 +400,8 @@ public override void WriteByte(byte value) this.writeOffset = 0; } - IMemoryOwner chunkBuffer = this.writeChunk.Buffer; - int chunkSize = this.writeChunk.Length; + IMemoryOwner? chunkBuffer = this.writeChunk?.Buffer; + int chunkSize = this.writeChunk!.Length; if (this.writeOffset == chunkSize) { @@ -412,7 +412,7 @@ public override void WriteByte(byte value) chunkBuffer = this.writeChunk.Buffer; } - chunkBuffer.GetSpan()[this.writeOffset++] = value; + chunkBuffer!.GetSpan()[this.writeOffset++] = value; } /// @@ -424,7 +424,7 @@ public byte[] ToArray() int length = (int)this.Length; // This will throw if stream is closed byte[] copy = new byte[this.Length]; - MemoryChunk backupReadChunk = this.readChunk; + MemoryChunk? backupReadChunk = this.readChunk; int backupReadOffset = this.readOffset; this.readChunk = this.memoryChunk; @@ -458,7 +458,7 @@ public void WriteTo(Stream stream) this.readOffset = 0; } - IMemoryOwner chunkBuffer = this.readChunk.Buffer; + IMemoryOwner? chunkBuffer = this.readChunk.Buffer; int chunkSize = this.readChunk.Length; if (this.readChunk.Next is null) { @@ -489,7 +489,7 @@ public void WriteTo(Stream stream) } int writeCount = chunkSize - this.readOffset; - stream.Write(chunkBuffer.GetSpan(), this.readOffset, writeCount); + stream.Write(chunkBuffer!.GetSpan(), this.readOffset, writeCount); this.readOffset = chunkSize; } } @@ -528,7 +528,7 @@ private MemoryChunk AllocateMemoryChunk() }; } - private static void ReleaseMemoryChunks(MemoryChunk chunk) + private static void ReleaseMemoryChunks(MemoryChunk? chunk) { while (chunk != null) { @@ -553,9 +553,9 @@ private sealed class MemoryChunk : IDisposable { private bool isDisposed; - public IMemoryOwner Buffer { get; set; } + public IMemoryOwner? Buffer { get; set; } - public MemoryChunk Next { get; set; } + public MemoryChunk? Next { get; set; } public int Length { get; set; } @@ -565,7 +565,7 @@ private void Dispose(bool disposing) { if (disposing) { - this.Buffer.Dispose(); + this.Buffer!.Dispose(); } this.Buffer = null; diff --git a/src/ImageSharp/Image.Decode.cs b/src/ImageSharp/Image.Decode.cs index 6953da1cea..f395a19b12 100644 --- a/src/ImageSharp/Image.Decode.cs +++ b/src/ImageSharp/Image.Decode.cs @@ -44,7 +44,7 @@ internal static Image CreateUninitialized( /// The general configuration. /// The image stream to read the header from. /// The mime type or null if none found. - private static IImageFormat InternalDetectFormat(Configuration configuration, Stream stream) + 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 // to ensure that only formats that headers fit within the given buffer length are tested. @@ -76,12 +76,12 @@ private static IImageFormat InternalDetectFormat(Configuration configuration, St // 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) { - IImageFormat attemptFormat = formatDetector.DetectFormat(headersBuffer); + IImageFormat? attemptFormat = formatDetector.DetectFormat(headersBuffer); if (attemptFormat != null) { format = attemptFormat; @@ -99,7 +99,7 @@ private static IImageFormat InternalDetectFormat(Configuration configuration, St /// 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) + private static IImageDecoder? DiscoverDecoder(DecoderOptions options, Stream stream, out IImageFormat? format) { format = InternalDetectFormat(options.Configuration, stream); @@ -118,10 +118,10 @@ private static IImageDecoder DiscoverDecoder(DecoderOptions options, Stream stre /// /// A new . /// - private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) + private static (Image? Image, IImageFormat? Format) Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel { - IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); + IImageDecoder? decoder = DiscoverDecoder(options, stream, out IImageFormat? format); if (decoder is null) { return (null, null); @@ -131,9 +131,9 @@ private static (Image Image, IImageFormat Format) Decode(Decoder return (img, format); } - private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) + private static (Image? Image, IImageFormat? Format) Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); + IImageDecoder? decoder = DiscoverDecoder(options, stream, out IImageFormat? format); if (decoder is null) { return (null, null); @@ -152,16 +152,16 @@ private static (Image Image, IImageFormat Format) Decode(DecoderOptions options, /// /// The or null if a suitable info detector is not found. /// - private static (IImageInfo ImageInfo, IImageFormat Format) InternalIdentity(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) + private static (IImageInfo? ImageInfo, IImageFormat? Format) InternalIdentity(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - IImageDecoder decoder = DiscoverDecoder(options, stream, out IImageFormat format); + IImageDecoder? decoder = DiscoverDecoder(options, stream, out IImageFormat? format); if (decoder is not IImageInfoDetector detector) { return (null, null); } - IImageInfo info = detector?.Identify(options, stream, cancellationToken); + IImageInfo? info = detector?.Identify(options, stream, cancellationToken); return (info, format); } } diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index d7d1f26913..513564f763 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -16,7 +16,7 @@ public abstract partial class Image /// /// The byte span containing encoded image data to read the header from. /// The format or null if none found. - public static IImageFormat DetectFormat(ReadOnlySpan data) + public static IImageFormat? DetectFormat(ReadOnlySpan data) => DetectFormat(DecoderOptions.Default, data); /// @@ -26,7 +26,7 @@ public static IImageFormat DetectFormat(ReadOnlySpan data) /// The byte span containing encoded image data to read the header from. /// The options are null. /// The mime type or null if none found. - public static IImageFormat DetectFormat(DecoderOptions options, ReadOnlySpan data) + public static IImageFormat? DetectFormat(DecoderOptions options, ReadOnlySpan data) { Guard.NotNull(options, nameof(options.Configuration)); @@ -39,7 +39,7 @@ public static IImageFormat DetectFormat(DecoderOptions options, ReadOnlySpan /// The or null if suitable info detector not found. /// - public static IImageInfo Identify(ReadOnlySpan data) => Identify(data, out IImageFormat _); + public static IImageInfo? Identify(ReadOnlySpan data) => Identify(data, out IImageFormat? _); /// /// Reads the raw image information from the specified stream without fully decoding it. @@ -71,7 +71,7 @@ public static IImageFormat DetectFormat(DecoderOptions options, ReadOnlySpan /// The or null if suitable info detector not found. /// - public static IImageInfo Identify(ReadOnlySpan data, out IImageFormat format) + public static IImageInfo? Identify(ReadOnlySpan data, out IImageFormat? format) => Identify(DecoderOptions.Default, data, out format); /// @@ -86,7 +86,7 @@ public static IImageInfo Identify(ReadOnlySpan data, out IImageFormat form /// /// The or null if suitable info detector is not found. /// - public static unsafe IImageInfo Identify(DecoderOptions options, ReadOnlySpan data, out IImageFormat format) + public static unsafe IImageInfo? Identify(DecoderOptions options, ReadOnlySpan data, out IImageFormat? format) { fixed (byte* ptr = data) { @@ -118,7 +118,7 @@ public static Image Load(ReadOnlySpan data) /// Image contains invalid content. /// Image format is not supported. /// A new . - public static Image Load(ReadOnlySpan data, out IImageFormat format) + public static Image Load(ReadOnlySpan data, out IImageFormat? format) where TPixel : unmanaged, IPixel => Load(DecoderOptions.Default, data, out format); @@ -158,7 +158,7 @@ public static unsafe Image Load(DecoderOptions options, ReadOnly public static unsafe Image Load( DecoderOptions options, ReadOnlySpan data, - out IImageFormat format) + out IImageFormat? format) where TPixel : unmanaged, IPixel { fixed (byte* ptr = data) @@ -189,7 +189,7 @@ public static Image Load(ReadOnlySpan data) /// Image contains invalid content. /// Image format is not supported. /// The . - public static Image Load(ReadOnlySpan data, out IImageFormat format) + public static Image Load(ReadOnlySpan data, out IImageFormat? format) => Load(DecoderOptions.Default, data, out format); /// @@ -215,7 +215,7 @@ public static Image Load(DecoderOptions options, ReadOnlySpan data) public static unsafe Image Load( DecoderOptions options, ReadOnlySpan data, - out IImageFormat format) + out IImageFormat? format) { fixed (byte* ptr = data) { diff --git a/src/ImageSharp/Image.FromFile.cs b/src/ImageSharp/Image.FromFile.cs index 199d450b89..6f01968fcc 100644 --- a/src/ImageSharp/Image.FromFile.cs +++ b/src/ImageSharp/Image.FromFile.cs @@ -16,7 +16,7 @@ public abstract partial class Image /// /// The image file to open and to read the header from. /// The mime type or null if none found. - public static IImageFormat DetectFormat(string filePath) + public static IImageFormat? DetectFormat(string filePath) => DetectFormat(DecoderOptions.Default, filePath); /// @@ -26,7 +26,7 @@ public static IImageFormat DetectFormat(string filePath) /// The image file to open and to read the header from. /// The configuration is null. /// The mime type or null if none found. - public static IImageFormat DetectFormat(DecoderOptions options, string filePath) + public static IImageFormat? DetectFormat(DecoderOptions options, string filePath) { Guard.NotNull(options, nameof(options)); @@ -41,8 +41,8 @@ public static IImageFormat DetectFormat(DecoderOptions options, string filePath) /// /// The or null if suitable info detector not found. /// - public static IImageInfo Identify(string filePath) - => Identify(filePath, out IImageFormat _); + public static IImageInfo? Identify(string filePath) + => Identify(filePath, out IImageFormat? _); /// /// Reads the raw image information from the specified stream without fully decoding it. @@ -52,7 +52,7 @@ public static IImageInfo Identify(string filePath) /// /// The or null if suitable info detector not found. /// - public static IImageInfo Identify(string filePath, out IImageFormat format) + public static IImageInfo? Identify(string filePath, out IImageFormat? format) => Identify(DecoderOptions.Default, filePath, out format); /// @@ -65,7 +65,7 @@ public static IImageInfo Identify(string filePath, out IImageFormat format) /// /// The or null if suitable info detector is not found. /// - public static IImageInfo Identify(DecoderOptions options, string filePath, out IImageFormat format) + public static IImageInfo? Identify(DecoderOptions options, string filePath, out IImageFormat? format) { Guard.NotNull(options, nameof(options)); using Stream file = options.Configuration.FileSystem.OpenRead(filePath); @@ -82,7 +82,7 @@ public static IImageInfo Identify(DecoderOptions options, string filePath, out I /// 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) + public static Task IdentifyAsync(string filePath, CancellationToken cancellationToken = default) => IdentifyAsync(DecoderOptions.Default, filePath, cancellationToken); /// @@ -96,12 +96,12 @@ public static Task IdentifyAsync(string filePath, CancellationToken /// 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( + public static async Task IdentifyAsync( DecoderOptions options, string filePath, CancellationToken cancellationToken = default) { - (IImageInfo ImageInfo, IImageFormat Format) res = + (IImageInfo? ImageInfo, IImageFormat? Format) res = await IdentifyWithFormatAsync(options, filePath, cancellationToken).ConfigureAwait(false); return res.ImageInfo; } @@ -116,7 +116,7 @@ public static async Task IdentifyAsync( /// 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( + public static Task<(IImageInfo? ImageInfo, IImageFormat? Format)> IdentifyWithFormatAsync( string filePath, CancellationToken cancellationToken = default) => IdentifyWithFormatAsync(DecoderOptions.Default, filePath, cancellationToken); @@ -132,7 +132,7 @@ public static async Task IdentifyAsync( /// The representing the asynchronous operation with the parameter type /// property set to null if suitable info detector is not found. /// - public static async Task<(IImageInfo ImageInfo, IImageFormat Format)> IdentifyWithFormatAsync( + public static async Task<(IImageInfo? ImageInfo, IImageFormat? Format)> IdentifyWithFormatAsync( DecoderOptions options, string filePath, CancellationToken cancellationToken = default) @@ -163,7 +163,7 @@ public static Image Load(string path) /// Thrown if the stream is not readable nor seekable. /// /// A new . - public static Image Load(string path, out IImageFormat format) + public static Image Load(string path, out IImageFormat? format) => Load(DecoderOptions.Default, path, out format); /// @@ -192,13 +192,13 @@ public static Image Load(DecoderOptions options, string path) /// Image format is not supported. /// Image contains invalid content. /// A representing the asynchronous operation. - public static async Task LoadAsync( + public static async Task LoadAsync( DecoderOptions options, string path, CancellationToken cancellationToken = default) { using Stream stream = options.Configuration.FileSystem.OpenRead(path); - (Image img, _) = await LoadWithFormatAsync(options, stream, cancellationToken) + (Image? img, _) = await LoadWithFormatAsync(options, stream, cancellationToken) .ConfigureAwait(false); return img; } @@ -215,7 +215,7 @@ public static async Task LoadAsync( /// Image format is not supported. /// Image contains invalid content. /// A representing the asynchronous operation. - public static Task LoadAsync(string path, CancellationToken cancellationToken = default) + public static Task LoadAsync(string path, CancellationToken cancellationToken = default) => LoadAsync(DecoderOptions.Default, path, cancellationToken); /// @@ -230,7 +230,7 @@ public static Task LoadAsync(string path, CancellationToken cancellationT /// Image format is not supported. /// The pixel format. /// A representing the asynchronous operation. - public static Task> LoadAsync(string path, CancellationToken cancellationToken = default) + public static Task?> LoadAsync(string path, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel => LoadAsync(DecoderOptions.Default, path, cancellationToken); @@ -247,7 +247,7 @@ public static Task> LoadAsync(string path, CancellationTok /// Image contains invalid content. /// The pixel format. /// A representing the asynchronous operation. - public static async Task> LoadAsync( + public static async Task?> LoadAsync( DecoderOptions options, string path, CancellationToken cancellationToken = default) @@ -256,7 +256,7 @@ public static async Task> LoadAsync( Guard.NotNull(options, nameof(options)); using Stream stream = options.Configuration.FileSystem.OpenRead(path); - (Image img, _) = + (Image? img, _) = await LoadWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false); return img; } @@ -286,7 +286,7 @@ public static Image Load(string path) /// Image format is not supported. /// The pixel format. /// A new . - public static Image Load(string path, out IImageFormat format) + public static Image Load(string path, out IImageFormat? format) where TPixel : unmanaged, IPixel => Load(DecoderOptions.Default, path, out format); @@ -325,7 +325,7 @@ public static Image Load(DecoderOptions options, string path) /// Image contains invalid content. /// The pixel format. /// A new . - public static Image Load(DecoderOptions options, string path, out IImageFormat format) + public static Image Load(DecoderOptions options, string path, out IImageFormat? format) where TPixel : unmanaged, IPixel { Guard.NotNull(options, nameof(options)); @@ -348,7 +348,7 @@ public static Image Load(DecoderOptions options, string path, ou /// Image format is not supported. /// Image contains invalid content. /// A new . - public static Image Load(DecoderOptions options, string path, out IImageFormat format) + public static Image Load(DecoderOptions options, string path, out IImageFormat? format) { Guard.NotNull(options, nameof(options)); Guard.NotNull(path, nameof(path)); diff --git a/src/ImageSharp/Image.FromStream.cs b/src/ImageSharp/Image.FromStream.cs index eb33ea9978..de9efe446e 100644 --- a/src/ImageSharp/Image.FromStream.cs +++ b/src/ImageSharp/Image.FromStream.cs @@ -22,7 +22,7 @@ public abstract partial class Image /// The stream is null. /// The stream is not readable. /// The format type or null if none found. - public static IImageFormat DetectFormat(Stream stream) + public static IImageFormat? DetectFormat(Stream stream) => DetectFormat(DecoderOptions.Default, stream); /// @@ -34,7 +34,7 @@ public static IImageFormat DetectFormat(Stream stream) /// The stream is null. /// The stream is not readable. /// The format type or null if none found. - public static IImageFormat DetectFormat(DecoderOptions options, Stream stream) + public static IImageFormat? DetectFormat(DecoderOptions options, Stream stream) => WithSeekableStream(options, stream, s => InternalDetectFormat(options.Configuration, s)); /// @@ -45,7 +45,7 @@ public static IImageFormat DetectFormat(DecoderOptions options, Stream stream) /// 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) + public static Task DetectFormatAsync(Stream stream, CancellationToken cancellationToken = default) => DetectFormatAsync(DecoderOptions.Default, stream, cancellationToken); /// @@ -58,7 +58,7 @@ public static Task DetectFormatAsync(Stream stream, CancellationTo /// 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) + public static Task DetectFormatAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) => WithSeekableStreamAsync( options, stream, @@ -75,8 +75,8 @@ public static Task DetectFormatAsync(DecoderOptions options, Strea /// /// The or null if a suitable info detector is not found. /// - public static IImageInfo Identify(Stream stream) - => Identify(stream, out IImageFormat _); + public static IImageInfo? Identify(Stream stream) + => Identify(stream, out IImageFormat? _); /// /// Reads the raw image information from the specified stream without fully decoding it. @@ -90,7 +90,7 @@ public static IImageInfo Identify(Stream stream) /// A representing the asynchronous operation or null if /// a suitable detector is not found. /// - public static Task IdentifyAsync(Stream stream, CancellationToken cancellationToken = default) + public static Task IdentifyAsync(Stream stream, CancellationToken cancellationToken = default) => IdentifyAsync(DecoderOptions.Default, stream, cancellationToken); /// @@ -104,7 +104,7 @@ public static Task IdentifyAsync(Stream stream, CancellationToken ca /// /// The or null if a suitable info detector is not found. /// - public static IImageInfo Identify(Stream stream, out IImageFormat format) + public static IImageInfo? Identify(Stream stream, out IImageFormat? format) => Identify(DecoderOptions.Default, stream, out format); /// @@ -119,7 +119,7 @@ public static IImageInfo Identify(Stream stream, out IImageFormat format) /// /// The or null if a suitable info detector is not found. /// - public static IImageInfo Identify(DecoderOptions options, Stream stream) + public static IImageInfo? Identify(DecoderOptions options, Stream stream) => Identify(options, stream, out _); /// @@ -136,12 +136,12 @@ public static IImageInfo Identify(DecoderOptions options, Stream stream) /// A representing the asynchronous operation or null if /// a suitable detector is not found. /// - public static async Task IdentifyAsync( + public static async Task IdentifyAsync( DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - (IImageInfo ImageInfo, IImageFormat Format) res = await IdentifyWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false); + (IImageInfo? ImageInfo, IImageFormat? Format) res = await IdentifyWithFormatAsync(options, stream, cancellationToken).ConfigureAwait(false); return res.ImageInfo; } @@ -158,9 +158,9 @@ public static async Task IdentifyAsync( /// /// The or null if a suitable info detector is not found. /// - public static IImageInfo Identify(DecoderOptions options, Stream stream, out IImageFormat format) + public static IImageInfo? Identify(DecoderOptions options, Stream stream, out IImageFormat? format) { - (IImageInfo ImageInfo, IImageFormat Format) data = WithSeekableStream(options, stream, s => InternalIdentity(options, s)); + (IImageInfo? ImageInfo, IImageFormat? Format) data = WithSeekableStream(options, stream, s => InternalIdentity(options, s)); format = data.Format; return data.ImageInfo; @@ -179,7 +179,7 @@ public static IImageInfo Identify(DecoderOptions options, Stream stream, out IIm /// 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( + public static Task<(IImageInfo? ImageInfo, IImageFormat? Format)> IdentifyWithFormatAsync( Stream stream, CancellationToken cancellationToken = default) => IdentifyWithFormatAsync(DecoderOptions.Default, stream, cancellationToken); @@ -198,7 +198,7 @@ public static IImageInfo Identify(DecoderOptions options, Stream stream, out IIm /// 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( + public static Task<(IImageInfo? ImageInfo, IImageFormat? Format)> IdentifyWithFormatAsync( DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) @@ -219,7 +219,7 @@ public static IImageInfo Identify(DecoderOptions options, Stream stream, out IIm /// Image format not recognised. /// Image contains invalid content. /// The . - public static Image Load(Stream stream, out IImageFormat format) + public static Image Load(Stream stream, out IImageFormat? format) => Load(DecoderOptions.Default, stream, out format); /// @@ -233,7 +233,7 @@ public static Image Load(Stream stream, out IImageFormat format) /// 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) + public static Task<(Image? Image, IImageFormat? Format)> LoadWithFormatAsync(Stream stream, CancellationToken cancellationToken = default) => LoadWithFormatAsync(DecoderOptions.Default, stream, cancellationToken); /// @@ -259,7 +259,7 @@ public static Image Load(Stream stream, out IImageFormat format) /// Image format not recognised. /// Image contains invalid content. /// A representing the asynchronous operation. - public static Task LoadAsync(Stream stream, CancellationToken cancellationToken = default) + public static Task LoadAsync(Stream stream, CancellationToken cancellationToken = default) => LoadAsync(DecoderOptions.Default, stream, cancellationToken); /// @@ -288,9 +288,9 @@ public static Image Load(DecoderOptions options, Stream stream) /// 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) + public static async Task LoadAsync(DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - (Image Image, IImageFormat Format) fmt = await LoadWithFormatAsync(options, stream, cancellationToken) + (Image? Image, IImageFormat? Format) fmt = await LoadWithFormatAsync(options, stream, cancellationToken) .ConfigureAwait(false); return fmt.Image; } @@ -320,7 +320,7 @@ public static Image Load(Stream stream) /// Image contains invalid content. /// The pixel format. /// A representing the asynchronous operation. - public static Task> LoadAsync(Stream stream, CancellationToken cancellationToken = default) + public static Task?> LoadAsync(Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel => LoadAsync(DecoderOptions.Default, stream, cancellationToken); @@ -335,7 +335,7 @@ public static Task> LoadAsync(Stream stream, CancellationT /// Image contains invalid content. /// The pixel format. /// A new . - public static Image Load(Stream stream, out IImageFormat format) + public static Image Load(Stream stream, out IImageFormat? format) where TPixel : unmanaged, IPixel => Load(DecoderOptions.Default, stream, out format); @@ -350,7 +350,7 @@ public static Image Load(Stream stream, out IImageFormat format) /// 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) + public static Task<(Image? Image, IImageFormat? Format)> LoadWithFormatAsync(Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel => LoadWithFormatAsync(DecoderOptions.Default, stream, cancellationToken); @@ -368,7 +368,7 @@ public static Image Load(Stream stream, out IImageFormat format) /// A new . public static Image Load(DecoderOptions options, Stream stream) where TPixel : unmanaged, IPixel - => Load(options, stream, out IImageFormat _); + => Load(options, stream, out IImageFormat? _); /// /// Create a new instance of the class from the given stream. @@ -383,10 +383,10 @@ public static Image Load(DecoderOptions options, Stream stream) /// Image contains invalid content. /// The pixel format. /// A representing the asynchronous operation. - public static Image Load(DecoderOptions options, Stream stream, out IImageFormat format) + 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)); + (Image? Image, IImageFormat? Format) data = WithSeekableStream(options, stream, s => Decode(options, s)); format = data.Format; @@ -410,12 +410,12 @@ public static Image Load(DecoderOptions options, Stream stream, /// Image format not recognised. /// Image contains invalid content. /// A representing the asynchronous operation. - public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync( + public static async Task<(Image? Image, IImageFormat? Format)> LoadWithFormatAsync( DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) { - (Image Image, IImageFormat Format) data = + (Image? Image, IImageFormat? Format) data = await WithSeekableStreamAsync(options, stream, (s, ct) => Decode(options, s, ct), cancellationToken) .ConfigureAwait(false); @@ -440,13 +440,13 @@ await WithSeekableStreamAsync(options, stream, (s, ct) => Decode(options, s, ct) /// Image contains invalid content. /// The pixel format. /// A representing the asynchronous operation. - public static async Task<(Image Image, IImageFormat Format)> LoadWithFormatAsync( + public static async Task<(Image? Image, IImageFormat? Format)> LoadWithFormatAsync( DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel { - (Image Image, IImageFormat Format) data = + (Image? Image, IImageFormat? Format) data = await WithSeekableStreamAsync(options, stream, (s, ct) => Decode(options, s, ct), cancellationToken) .ConfigureAwait(false); @@ -471,13 +471,13 @@ await WithSeekableStreamAsync(options, stream, (s, ct) => Decode(options /// Image contains invalid content. /// The pixel format. /// A representing the asynchronous operation. - public static async Task> LoadAsync( + public static async Task?> LoadAsync( DecoderOptions options, Stream stream, CancellationToken cancellationToken = default) where TPixel : unmanaged, IPixel { - (Image img, _) = await LoadWithFormatAsync(options, stream, cancellationToken) + (Image ?img, _) = await LoadWithFormatAsync(options, stream, cancellationToken) .ConfigureAwait(false); return img; } @@ -495,9 +495,9 @@ public static async Task> LoadAsync( /// Image format not recognised. /// Image contains invalid content. /// A new . - public static Image Load(DecoderOptions options, Stream stream, out IImageFormat format) + public static Image Load(DecoderOptions options, Stream stream, out IImageFormat? format) { - (Image img, IImageFormat fmt) = WithSeekableStream(options, stream, s => Decode(options, s)); + (Image? img, IImageFormat? fmt) = WithSeekableStream(options, stream, s => Decode(options, s)); format = fmt; diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs index 9a37adb3c0..98fba0a141 100644 --- a/src/ImageSharp/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image.LoadPixelData.cs @@ -74,7 +74,7 @@ public static Image LoadPixelData(Configuration configuration, R var image = new Image(configuration, width, height); data = data[..count]; - data.CopyTo(image.Frames.RootFrame.PixelBuffer.FastMemoryGroup); + data.CopyTo(image.Frames.RootFrame.PixelBuffer!.FastMemoryGroup); return image; } diff --git a/src/ImageSharp/ImageExtensions.Internal.cs b/src/ImageSharp/ImageExtensions.Internal.cs index 76c9b85224..88d48d03fc 100644 --- a/src/ImageSharp/ImageExtensions.Internal.cs +++ b/src/ImageSharp/ImageExtensions.Internal.cs @@ -25,6 +25,6 @@ public static partial class ImageExtensions internal static Buffer2D GetRootFramePixelBuffer(this Image image) where TPixel : unmanaged, IPixel { - return image.Frames.RootFrame.PixelBuffer; + return image.Frames.RootFrame.PixelBuffer!; } } diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs index e79fceeaa0..a98a6b80e1 100644 --- a/src/ImageSharp/ImageExtensions.cs +++ b/src/ImageSharp/ImageExtensions.cs @@ -98,7 +98,7 @@ public static void Save(this Image source, Stream stream, IImageFormat format) throw new NotSupportedException("Cannot write to the stream."); } - IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); + IImageEncoder? encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); if (encoder is null) { @@ -142,7 +142,7 @@ public static Task SaveAsync( throw new NotSupportedException("Cannot write to the stream."); } - IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); + IImageEncoder? encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format); if (encoder is null) { @@ -183,6 +183,6 @@ public static string ToBase64String(this Image source, IImageFormat format) // Always available. stream.TryGetBuffer(out ArraySegment buffer); - return $"data:{format.DefaultMimeType};base64,{Convert.ToBase64String(buffer.Array, 0, (int)stream.Length)}"; + return $"data:{format.DefaultMimeType};base64,{Convert.ToBase64String(buffer.Array!, 0, (int)stream.Length)}"; } } diff --git a/src/ImageSharp/ImageFrame.LoadPixelData.cs b/src/ImageSharp/ImageFrame.LoadPixelData.cs index 61f4c0ea9d..792654dede 100644 --- a/src/ImageSharp/ImageFrame.LoadPixelData.cs +++ b/src/ImageSharp/ImageFrame.LoadPixelData.cs @@ -43,7 +43,7 @@ internal static ImageFrame LoadPixelData(Configuration configura var image = new ImageFrame(configuration, width, height); data = data[..count]; - data.CopyTo(image.PixelBuffer.FastMemoryGroup); + data.CopyTo(image.PixelBuffer!.FastMemoryGroup); return image; } diff --git a/src/ImageSharp/ImageFrameCollection.cs b/src/ImageSharp/ImageFrameCollection.cs index 1632134260..7a2d344450 100644 --- a/src/ImageSharp/ImageFrameCollection.cs +++ b/src/ImageSharp/ImageFrameCollection.cs @@ -69,7 +69,7 @@ public ImageFrame this[int index] /// The to clone and insert into the . /// Frame must have the same dimensions as the image. /// The cloned . - public ImageFrame InsertFrame(int index, ImageFrame source) + public ImageFrame InsertFrame(int index, ImageFrame? source) { this.EnsureNotDisposed(); @@ -81,7 +81,7 @@ public ImageFrame InsertFrame(int index, ImageFrame source) /// /// The raw pixel data to generate the from. /// The cloned . - public ImageFrame AddFrame(ImageFrame source) + public ImageFrame AddFrame(ImageFrame? source) { this.EnsureNotDisposed(); @@ -226,14 +226,14 @@ protected void EnsureNotDisposed() /// The index. /// The frame. /// The new frame. - protected abstract ImageFrame NonGenericInsertFrame(int index, ImageFrame source); + protected abstract ImageFrame NonGenericInsertFrame(int index, ImageFrame? source); /// /// Implements . /// /// The frame. /// The new frame. - protected abstract ImageFrame NonGenericAddFrame(ImageFrame source); + protected abstract ImageFrame NonGenericAddFrame(ImageFrame? source); /// /// Implements . diff --git a/src/ImageSharp/ImageFrameCollection{TPixel}.cs b/src/ImageSharp/ImageFrameCollection{TPixel}.cs index 60b5c6d6ad..ce884e3a48 100644 --- a/src/ImageSharp/ImageFrameCollection{TPixel}.cs +++ b/src/ImageSharp/ImageFrameCollection{TPixel}.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System.Collections; +using System.Diagnostics.CodeAnalysis; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -133,7 +134,7 @@ public int IndexOf(ImageFrame frame) /// The to clone and insert into the . /// Frame must have the same dimensions as the image. /// The cloned . - public ImageFrame InsertFrame(int index, ImageFrame source) + public ImageFrame InsertFrame(int index, ImageFrame? source) { this.EnsureNotDisposed(); @@ -313,7 +314,7 @@ public override void MoveFrame(int sourceIndex, int destinationIndex) protected override ImageFrame NonGenericGetFrame(int index) => this[index]; /// - protected override ImageFrame NonGenericInsertFrame(int index, ImageFrame source) + protected override ImageFrame NonGenericInsertFrame(int index, ImageFrame? source) { Guard.NotNull(source, nameof(source)); @@ -328,7 +329,7 @@ protected override ImageFrame NonGenericInsertFrame(int index, ImageFrame source } /// - protected override ImageFrame NonGenericAddFrame(ImageFrame source) + protected override ImageFrame NonGenericAddFrame(ImageFrame? source) { Guard.NotNull(source, nameof(source)); @@ -379,7 +380,7 @@ public ImageFrame CreateFrame(TPixel backgroundColor) /// IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this.frames).GetEnumerator(); - private void ValidateFrame(ImageFrame frame) + private void ValidateFrame([NotNull]ImageFrame? frame) { Guard.NotNull(frame, nameof(frame)); @@ -412,7 +413,7 @@ private ImageFrame CopyNonCompatibleFrame(ImageFrame source) this.parent.GetConfiguration(), source.Size(), source.Metadata.DeepClone()); - source.CopyPixelsTo(result.PixelBuffer.FastMemoryGroup); + source.CopyPixelsTo(result.PixelBuffer!.FastMemoryGroup); return result; } } diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs index d8708135ef..83b4347c13 100644 --- a/src/ImageSharp/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/ImageFrame{TPixel}.cs @@ -137,14 +137,14 @@ internal ImageFrame(Configuration configuration, ImageFrame source) Guard.NotNull(source, nameof(source)); this.PixelBuffer = this.GetConfiguration().MemoryAllocator.Allocate2D( - source.PixelBuffer.Width, + source.PixelBuffer!.Width, source.PixelBuffer.Height, configuration.PreferContiguousImageBuffers); source.PixelBuffer.FastMemoryGroup.CopyTo(this.PixelBuffer.FastMemoryGroup); } /// - public Buffer2D PixelBuffer { get; private set; } + public Buffer2D? PixelBuffer { get; private set; } /// /// Gets or sets the pixel at the specified position. @@ -159,14 +159,14 @@ internal ImageFrame(Configuration configuration, ImageFrame source) get { this.VerifyCoords(x, y); - return this.PixelBuffer.GetElementUnsafe(x, y); + return this.PixelBuffer!.GetElementUnsafe(x, y); } [MethodImpl(InliningOptions.ShortMethod)] set { this.VerifyCoords(x, y); - this.PixelBuffer.GetElementUnsafe(x, y) = value; + this.PixelBuffer!.GetElementUnsafe(x, y) = value; } } @@ -178,7 +178,7 @@ public void ProcessPixelRows(PixelAccessorAction processPixels) { Guard.NotNull(processPixels, nameof(processPixels)); - this.PixelBuffer.FastMemoryGroup.IncreaseRefCounts(); + this.PixelBuffer!.FastMemoryGroup.IncreaseRefCounts(); try { @@ -205,8 +205,8 @@ public void ProcessPixelRows( Guard.NotNull(frame2, nameof(frame2)); Guard.NotNull(processPixels, nameof(processPixels)); - this.PixelBuffer.FastMemoryGroup.IncreaseRefCounts(); - frame2.PixelBuffer.FastMemoryGroup.IncreaseRefCounts(); + this.PixelBuffer!.FastMemoryGroup.IncreaseRefCounts(); + frame2.PixelBuffer!.FastMemoryGroup.IncreaseRefCounts(); try { @@ -240,9 +240,9 @@ public void ProcessPixelRows( Guard.NotNull(frame3, nameof(frame3)); Guard.NotNull(processPixels, nameof(processPixels)); - this.PixelBuffer.FastMemoryGroup.IncreaseRefCounts(); - frame2.PixelBuffer.FastMemoryGroup.IncreaseRefCounts(); - frame3.PixelBuffer.FastMemoryGroup.IncreaseRefCounts(); + this.PixelBuffer!.FastMemoryGroup.IncreaseRefCounts(); + frame2.PixelBuffer!.FastMemoryGroup.IncreaseRefCounts(); + frame3.PixelBuffer!.FastMemoryGroup.IncreaseRefCounts(); try { @@ -303,7 +303,7 @@ public bool DangerousTryGetSinglePixelMemory(out Memory memory) /// The y-coordinate of the pixel. Must be greater than or equal to zero and less than the height of the image. /// The at the specified position. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ref TPixel GetPixelReference(int x, int y) => ref this.PixelBuffer[x, y]; + internal ref TPixel GetPixelReference(int x, int y) => ref this.PixelBuffer![x, y]; /// /// Copies the pixels to a of the same size. @@ -316,7 +316,7 @@ internal void CopyTo(Buffer2D target) throw new ArgumentException("ImageFrame.CopyTo(): target must be of the same size!", nameof(target)); } - this.PixelBuffer.FastMemoryGroup.CopyTo(target.FastMemoryGroup); + this.PixelBuffer!.FastMemoryGroup.CopyTo(target.FastMemoryGroup); } /// @@ -327,8 +327,8 @@ internal void SwapOrCopyPixelsBufferFrom(ImageFrame pixelSource) { Guard.NotNull(pixelSource, nameof(pixelSource)); - Buffer2D.SwapOrCopyContent(this.PixelBuffer, pixelSource.PixelBuffer); - this.UpdateSize(this.PixelBuffer.Size()); + Buffer2D.SwapOrCopyContent(this.PixelBuffer!, pixelSource.PixelBuffer!); + this.UpdateSize(this.PixelBuffer!.Size()); } /// @@ -352,7 +352,7 @@ internal override void CopyPixelsTo(MemoryGroup + this.PixelBuffer!.FastMemoryGroup.TransformTo(destination, (s, d) => { Span d1 = MemoryMarshal.Cast(d); s.CopyTo(d1); @@ -360,7 +360,7 @@ internal override void CopyPixelsTo(MemoryGroup PixelOperations.Instance.To(this.GetConfiguration(), s, d)); } @@ -399,11 +399,11 @@ internal ImageFrame CloneAs(Configuration configuration) { if (typeof(TPixel2) == typeof(TPixel)) { - return this.Clone(configuration) as ImageFrame; + return (this.Clone(configuration) as ImageFrame)!; } var target = new ImageFrame(configuration, this.Width, this.Height, this.Metadata.DeepClone()); - var operation = new RowIntervalOperation(this.PixelBuffer, target.PixelBuffer, configuration); + var operation = new RowIntervalOperation(this.PixelBuffer!, target.PixelBuffer!, configuration); ParallelRowIterator.IterateRowIntervals( configuration, @@ -419,7 +419,7 @@ internal ImageFrame CloneAs(Configuration configuration) /// The value to initialize the bitmap with. internal void Clear(TPixel value) { - MemoryGroup group = this.PixelBuffer.FastMemoryGroup; + MemoryGroup group = this.PixelBuffer!.FastMemoryGroup; if (value.Equals(default)) { diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 41ca9b9fa9..75d4b173c8 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -15,6 +15,12 @@ Debug;Release + + + enable + Nullable + + 3.0 diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 814843013e..5adfd23f6a 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using System.Buffers; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; @@ -187,7 +186,7 @@ internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable< this.EnsureNotDisposed(); this.VerifyCoords(x, y); - return this.PixelSourceUnsafe.PixelBuffer.GetElementUnsafe(x, y); + return this.PixelSourceUnsafe.PixelBuffer!.GetElementUnsafe(x, y); } [MethodImpl(InliningOptions.ShortMethod)] @@ -196,7 +195,7 @@ internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable< this.EnsureNotDisposed(); this.VerifyCoords(x, y); - this.PixelSourceUnsafe.PixelBuffer.GetElementUnsafe(x, y) = value; + this.PixelSourceUnsafe.PixelBuffer!.GetElementUnsafe(x, y) = value; } } @@ -207,7 +206,7 @@ internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable< public void ProcessPixelRows(PixelAccessorAction processPixels) { Guard.NotNull(processPixels, nameof(processPixels)); - Buffer2D buffer = this.Frames.RootFrame.PixelBuffer; + Buffer2D buffer = this.Frames.RootFrame.PixelBuffer!; buffer.FastMemoryGroup.IncreaseRefCounts(); try @@ -235,8 +234,8 @@ public void ProcessPixelRows( Guard.NotNull(image2, nameof(image2)); Guard.NotNull(processPixels, nameof(processPixels)); - Buffer2D buffer1 = this.Frames.RootFrame.PixelBuffer; - Buffer2D buffer2 = image2.Frames.RootFrame.PixelBuffer; + Buffer2D buffer1 = this.Frames.RootFrame.PixelBuffer!; + Buffer2D buffer2 = image2.Frames.RootFrame.PixelBuffer!; buffer1.FastMemoryGroup.IncreaseRefCounts(); buffer2.FastMemoryGroup.IncreaseRefCounts(); @@ -273,9 +272,9 @@ public void ProcessPixelRows( Guard.NotNull(image3, nameof(image3)); Guard.NotNull(processPixels, nameof(processPixels)); - Buffer2D buffer1 = this.Frames.RootFrame.PixelBuffer; - Buffer2D buffer2 = image2.Frames.RootFrame.PixelBuffer; - Buffer2D buffer3 = image3.Frames.RootFrame.PixelBuffer; + Buffer2D buffer1 = this.Frames.RootFrame.PixelBuffer!; + Buffer2D buffer2 = image2.Frames.RootFrame.PixelBuffer!; + Buffer2D buffer3 = image3.Frames.RootFrame.PixelBuffer!; buffer1.FastMemoryGroup.IncreaseRefCounts(); buffer2.FastMemoryGroup.IncreaseRefCounts(); @@ -427,7 +426,7 @@ private static Size ValidateFramesAndGetSize(IEnumerable> fra { Guard.NotNull(frames, nameof(frames)); - ImageFrame rootFrame = frames.FirstOrDefault(); + ImageFrame? rootFrame = frames.FirstOrDefault(); if (rootFrame == null) { diff --git a/src/ImageSharp/IndexedImageFrame{TPixel}.cs b/src/ImageSharp/IndexedImageFrame{TPixel}.cs index 3d37bf5bcc..12a78a0239 100644 --- a/src/ImageSharp/IndexedImageFrame{TPixel}.cs +++ b/src/ImageSharp/IndexedImageFrame{TPixel}.cs @@ -108,8 +108,6 @@ public void Dispose() this.isDisposed = true; this.pixelBuffer.Dispose(); this.paletteOwner.Dispose(); - this.pixelBuffer = null; - this.paletteOwner = null; } } } diff --git a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs index 173e916457..6f48c56696 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs @@ -14,8 +14,8 @@ namespace SixLabors.ImageSharp.Memory.Internals; /// internal sealed class Gen2GcCallback : CriticalFinalizerObject { - private readonly Func callback0; - private readonly Func callback1; + private readonly Func? callback0; + private readonly Func? callback1; private GCHandle weakTargetObj; private Gen2GcCallback(Func callback) => this.callback0 = callback; @@ -31,7 +31,7 @@ private Gen2GcCallback(Func callback, object targetObj) if (this.weakTargetObj.IsAllocated) { // Check to see if the target object is still alive. - object targetObj = this.weakTargetObj.Target; + object? targetObj = this.weakTargetObj.Target; if (targetObj == null) { // The target object is dead, so this callback object is no longer needed. @@ -42,7 +42,7 @@ private Gen2GcCallback(Func callback, object targetObj) // Execute the callback method. try { - if (!this.callback1(targetObj)) + if (!this.callback1!(targetObj)) { // If the callback returns false, this callback object is no longer needed. this.weakTargetObj.Free(); @@ -63,7 +63,7 @@ private Gen2GcCallback(Func callback, object targetObj) // Execute the callback method. try { - if (!this.callback0()) + if (!this.callback0!()) { // If the callback returns false, this callback object is no longer needed. return; diff --git a/src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs b/src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs index 0edc41434b..4a202a96c3 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs @@ -14,7 +14,7 @@ internal abstract class RefCountedMemoryLifetimeGuard : IDisposable private int refCount = 1; private int disposed; private int released; - private string allocationStackTrace; + private string? allocationStackTrace; protected RefCountedMemoryLifetimeGuard() { diff --git a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs index 5876fd429d..2da93312b0 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs @@ -21,7 +21,7 @@ public SharedArrayPoolBuffer(int lengthInElements) this.lifetimeGuard = new LifetimeGuard(this.Array); } - public byte[] Array { get; private set; } + public byte[]? Array { get; private set; } protected override void Dispose(bool disposing) { @@ -40,7 +40,7 @@ public override Span GetSpan() return MemoryMarshal.Cast(this.Array.AsSpan(0, this.lengthInBytes)); } - protected override object GetPinnableObject() => this.Array; + protected override object GetPinnableObject() => this.Array!; public void AddRef() { @@ -61,7 +61,7 @@ private void CheckDisposed() private sealed class LifetimeGuard : RefCountedMemoryLifetimeGuard { - private byte[] array; + private byte[]? array; public LifetimeGuard(byte[] array) => this.array = array; @@ -72,7 +72,7 @@ protected override void Release() // This is not ideal, but subsequent leaks will end up returning arrays to per-cpu buckets, // meaning likely a different bucket than it was rented from, // but this is PROBABLY better than not returning the arrays at all. - ArrayPool.Shared.Return(this.array); + ArrayPool.Shared.Return(this.array!); this.array = null; } } diff --git a/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs b/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs index 571d713b52..aa8bcd3859 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs @@ -12,7 +12,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx { private static int minTrimPeriodMilliseconds = int.MaxValue; private static readonly List> AllPools = new(); - private static Timer trimTimer; + private static Timer? trimTimer; private static readonly Stopwatch Stopwatch = Stopwatch.StartNew(); @@ -96,7 +96,7 @@ public UnmanagedMemoryHandle Rent() /// /// Rent buffers or return 'null' if the pool is full. /// - public UnmanagedMemoryHandle[] Rent(int bufferCount) + public UnmanagedMemoryHandle[]? Rent(int bufferCount) { UnmanagedMemoryHandle[] buffersLocal = this.buffers; @@ -247,7 +247,7 @@ private static void TimerCallback() foreach (WeakReference weakPoolRef in AllPools) { - if (weakPoolRef.TryGetTarget(out UniformUnmanagedMemoryPool pool)) + if (weakPoolRef.TryGetTarget(out UniformUnmanagedMemoryPool? pool)) { pool.Trim(); } diff --git a/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs b/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs index 5bf2a8f593..c13fa754e2 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs @@ -19,7 +19,7 @@ internal struct UnmanagedMemoryHandle : IEquatable private static long totalOomRetries; // A Monitor to wait/signal when we are low on memory. - private static object lowMemoryMonitor; + private static object? lowMemoryMonitor; public static readonly UnmanagedMemoryHandle NullHandle; @@ -113,9 +113,9 @@ public void Free() if (Volatile.Read(ref lowMemoryMonitor) != null) { // We are low on memory. Signal all threads waiting in AllocateHandle(). - Monitor.Enter(lowMemoryMonitor); - Monitor.PulseAll(lowMemoryMonitor); - Monitor.Exit(lowMemoryMonitor); + Monitor.Enter(lowMemoryMonitor!); + Monitor.PulseAll(lowMemoryMonitor!); + Monitor.Exit(lowMemoryMonitor!); } this.lengthInBytes = 0; @@ -123,7 +123,7 @@ public void Free() public bool Equals(UnmanagedMemoryHandle other) => this.handle.Equals(other.handle); - public override bool Equals(object obj) => obj is UnmanagedMemoryHandle other && this.Equals(other); + public override bool Equals(object? obj) => obj is UnmanagedMemoryHandle other && this.Equals(other); public override int GetHashCode() => this.handle.GetHashCode(); } diff --git a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs index bf75a716dd..8680bb2715 100644 --- a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs +++ b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs @@ -135,9 +135,9 @@ internal override MemoryGroup AllocateGroup( } // Attempt to rent the whole group from the pool, allocate a group of unmanaged buffers if the attempt fails: - if (MemoryGroup.TryAllocate(this.pool, totalLength, bufferAlignment, options, out MemoryGroup poolGroup)) + if (MemoryGroup.TryAllocate(this.pool, totalLength, bufferAlignment, options, out MemoryGroup? poolGroup)) { - return poolGroup; + return poolGroup!; } return MemoryGroup.Allocate(this.nonPoolAllocator, totalLength, bufferAlignment, options); diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index 2eb05ea935..2af84ba0a9 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -18,7 +18,7 @@ public static class Buffer2DExtensions /// The buffer. /// The element type. /// The MemoryGroup. - public static IMemoryGroup GetMemoryGroup(this Buffer2D buffer) + public static IMemoryGroup? GetMemoryGroup(this Buffer2D buffer) where T : struct { Guard.NotNull(buffer, nameof(buffer)); diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index 8d6465389f..5793d3b03b 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -43,7 +43,7 @@ internal Buffer2D(MemoryGroup memoryGroup, int width, int height) /// Gets the backing . /// /// The MemoryGroup. - public IMemoryGroup MemoryGroup => this.FastMemoryGroup.View; + public IMemoryGroup? MemoryGroup => this.FastMemoryGroup.View; /// /// Gets the backing without the view abstraction. @@ -138,7 +138,7 @@ internal Memory GetSafeRowMemory(int y) { DebugGuard.MustBeGreaterThanOrEqualTo(y, 0, nameof(y)); DebugGuard.MustBeLessThan(y, this.Height, nameof(y)); - return this.FastMemoryGroup.View.GetBoundedMemorySlice(y * (long)this.Width, this.Width); + return this.FastMemoryGroup.View!.GetBoundedMemorySlice(y * (long)this.Width, this.Width); } /// @@ -186,7 +186,7 @@ internal static bool SwapOrCopyContent(Buffer2D destination, Buffer2D sour "Trying to copy/swap incompatible buffers. This is most likely caused by applying an unsupported processor to wrapped-memory images."); } - source.FastMemoryGroup.CopyTo(destination.MemoryGroup); + source.FastMemoryGroup.CopyTo(destination.MemoryGroup!); } (destination.Width, source.Width) = (source.Width, destination.Width); diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs index 36abfba886..c4fbe61d6b 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs @@ -27,7 +27,7 @@ public static MemoryGroupSpanCache Create(IMemoryOwner[] memoryOwners) if (owner0 is SharedArrayPoolBuffer sharedPoolBuffer) { memoryGroupSpanCache.Mode = SpanCacheMode.SingleArray; - memoryGroupSpanCache.SingleArray = sharedPoolBuffer.Array; + memoryGroupSpanCache.SingleArray = sharedPoolBuffer.Array!; } else if (owner0 is UnmanagedBuffer unmanagedBuffer) { diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs index 333fede6a6..8f3ec17773 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Memory; internal class MemoryGroupView : IMemoryGroup where T : struct { - private MemoryGroup owner; + private MemoryGroup? owner; private readonly MemoryOwnerWrapper[] memoryWrappers; public MemoryGroupView(MemoryGroup owner) @@ -40,7 +40,7 @@ public int Count get { this.EnsureIsValid(); - return this.owner.Count; + return this.owner!.Count; } } @@ -49,7 +49,7 @@ public int BufferLength get { this.EnsureIsValid(); - return this.owner.BufferLength; + return this.owner!.BufferLength; } } @@ -58,7 +58,7 @@ public long TotalLength get { this.EnsureIsValid(); - return this.owner.TotalLength; + return this.owner!.TotalLength; } } @@ -125,13 +125,13 @@ protected override void Dispose(bool disposing) public override Span GetSpan() { this.view.EnsureIsValid(); - return this.view.owner[this.index].Span; + return this.view.owner![this.index].Span; } public override MemoryHandle Pin(int elementIndex = 0) { this.view.EnsureIsValid(); - return this.view.owner[this.index].Pin(); + return this.view.owner![this.index].Pin(); } public override void Unpin() diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs index 950e2a019e..03a2fb78f7 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs @@ -48,6 +48,6 @@ IEnumerator> IEnumerable>.GetEnumerator() return ((IList>)this.source).GetEnumerator(); } - public override void Dispose() => this.View.Invalidate(); + public override void Dispose() => this.View?.Invalidate(); } } diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs index 8637ea7a33..5495172ca4 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs @@ -15,7 +15,7 @@ internal abstract partial class MemoryGroup public sealed class Owned : MemoryGroup, IEnumerable> { private IMemoryOwner[] memoryOwners; - private RefCountedMemoryLifetimeGuard groupLifetimeGuard; + private RefCountedMemoryLifetimeGuard? groupLifetimeGuard; public Owned(IMemoryOwner[] memoryOwners, int bufferLength, long totalLength, bool swappable) : base(bufferLength, totalLength) @@ -122,7 +122,7 @@ public override void DecreaseRefCounts() public override void RecreateViewAfterSwap() { - this.View.Invalidate(); + this.View?.Invalidate(); this.View = new MemoryGroupView(this); } @@ -140,7 +140,7 @@ public override void Dispose() return; } - this.View.Invalidate(); + this.View?.Invalidate(); if (this.groupLifetimeGuard != null) { @@ -154,7 +154,6 @@ public override void Dispose() } } - this.memoryOwners = null; this.IsValid = false; this.groupLifetimeGuard = null; } diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs index c032316649..c7deea60d7 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs @@ -40,7 +40,7 @@ private MemoryGroup(int bufferLength, long totalLength) /// public bool IsValid { get; private set; } = true; - public MemoryGroupView View { get; private set; } + public MemoryGroupView? View { get; private set; } /// public abstract Memory this[int index] { get; } @@ -149,7 +149,7 @@ public static bool TryAllocate( long totalLengthInElements, int bufferAlignmentInElements, AllocationOptions options, - out MemoryGroup memoryGroup) + out MemoryGroup? memoryGroup) { Guard.NotNull(pool, nameof(pool)); Guard.MustBeGreaterThanOrEqualTo(totalLengthInElements, 0, nameof(totalLengthInElements)); @@ -187,7 +187,7 @@ public static bool TryAllocate( bufferCount++; } - UnmanagedMemoryHandle[] arrays = pool.Rent(bufferCount); + UnmanagedMemoryHandle[]? arrays = pool.Rent(bufferCount); if (arrays == null) { diff --git a/src/ImageSharp/Memory/RowInterval.cs b/src/ImageSharp/Memory/RowInterval.cs index 7f40c91565..90a88d735a 100644 --- a/src/ImageSharp/Memory/RowInterval.cs +++ b/src/ImageSharp/Memory/RowInterval.cs @@ -68,7 +68,7 @@ public bool Equals(RowInterval other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return !ReferenceEquals(null, obj) && obj is RowInterval other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/ImageFrameMetadata.cs b/src/ImageSharp/Metadata/ImageFrameMetadata.cs index 69ff5201f2..8fde313982 100644 --- a/src/ImageSharp/Metadata/ImageFrameMetadata.cs +++ b/src/ImageSharp/Metadata/ImageFrameMetadata.cs @@ -48,22 +48,22 @@ internal ImageFrameMetadata(ImageFrameMetadata other) /// /// 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 list of ICC profiles. /// - 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; } /// public ImageFrameMetadata DeepClone() => new(this); @@ -81,7 +81,7 @@ public TFormatFrameMetadata GetFormatMetadata /// 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 list of ICC profiles. /// - 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 metadata value associated with the specified key. @@ -164,7 +164,7 @@ public double VerticalResolution 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/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index 949dc23880..44dd858f36 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -26,7 +26,7 @@ internal static class ExifEncodedStringHelpers // 20932 EUC-JP Japanese (JIS 0208-1990 and 0212-1990) // https://docs.microsoft.com/en-us/dotnet/api/system.text.encoding?view=net-6.0 - private static Encoding JIS0208Encoding => CodePagesEncodingProvider.Instance.GetEncoding(20932); + private static Encoding? JIS0208Encoding => CodePagesEncodingProvider.Instance.GetEncoding(20932); public static bool IsEncodedString(ExifTagValue tag) => tag switch { @@ -43,7 +43,7 @@ internal static class ExifEncodedStringHelpers _ => UndefinedCodeBytes }; - public static Encoding GetEncoding(CharacterCode code) => code switch + public static Encoding? GetEncoding(CharacterCode code) => code switch { CharacterCode.ASCII => Encoding.ASCII, CharacterCode.JIS => JIS0208Encoding, @@ -56,7 +56,7 @@ public static bool TryParse(ReadOnlySpan buffer, out EncodedString encoded { if (TryDetect(buffer, out CharacterCode code)) { - string text = GetEncoding(code).GetString(buffer[CharacterCodeBytesLength..]); + string text = GetEncoding(code)!.GetString(buffer[CharacterCodeBytesLength..]); encodedString = new EncodedString(code, text); return true; } @@ -66,14 +66,14 @@ public static bool TryParse(ReadOnlySpan buffer, out EncodedString encoded } public static uint GetDataLength(EncodedString encodedString) => - (uint)GetEncoding(encodedString.Code).GetByteCount(encodedString.Text) + CharacterCodeBytesLength; + (uint)GetEncoding(encodedString.Code)!.GetByteCount(encodedString.Text) + CharacterCodeBytesLength; public static int Write(EncodedString encodedString, Span destination) { GetCodeBytes(encodedString.Code).CopyTo(destination); string text = encodedString.Text; - int count = Write(GetEncoding(encodedString.Code), text, destination[CharacterCodeBytesLength..]); + int count = Write(GetEncoding(encodedString.Code)!, text, destination[CharacterCodeBytesLength..]); return CharacterCodeBytesLength + count; } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs index 93c5cea3cb..f8ef9c55bb 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -13,12 +14,12 @@ public sealed class ExifProfile : IDeepCloneable /// /// The byte array to read the EXIF profile from. /// - private readonly byte[] data; + private readonly byte[]? data; /// /// The collection of EXIF values /// - private List values; + private List? values; /// /// The thumbnail offset position in the byte stream @@ -34,7 +35,7 @@ public sealed class ExifProfile : IDeepCloneable /// Initializes a new instance of the class. /// public ExifProfile() - : this((byte[])null) + : this((byte[]?)null) { } @@ -42,7 +43,7 @@ public ExifProfile() /// Initializes a new instance of the class. /// /// The byte array to read the EXIF profile from. - public ExifProfile(byte[] data) + public ExifProfile(byte[]? data) { this.Parts = ExifParts.All; this.data = data; @@ -124,7 +125,7 @@ public IReadOnlyList Values /// /// The . /// - public Image CreateThumbnail() => this.CreateThumbnail(); + public Image? CreateThumbnail() => this.CreateThumbnail(); /// /// Returns the thumbnail in the EXIF profile when available. @@ -133,7 +134,7 @@ public IReadOnlyList Values /// /// The . /// - public Image CreateThumbnail() + public Image? CreateThumbnail() where TPixel : unmanaged, IPixel { this.InitializeValues(); @@ -160,9 +161,9 @@ public Image CreateThumbnail() /// The tag of the exif value. /// The value with the specified tag. /// The data type of the tag. - public IExifValue GetValue(ExifTag tag) + public IExifValue? GetValue(ExifTag tag) { - IExifValue value = this.GetValueInternal(tag); + IExifValue? value = this.GetValueInternal(tag); return value is null ? null : (IExifValue)value; } @@ -206,7 +207,7 @@ public byte[] ToByteArray() { if (this.values is null) { - return this.data; + return this.data!; } if (this.values.Count == 0) @@ -226,7 +227,7 @@ public byte[] ToByteArray() /// /// The tag of the exif value. /// The value with the specified tag. - internal IExifValue GetValueInternal(ExifTag tag) + internal IExifValue? GetValueInternal(ExifTag tag) { foreach (IExifValue exifValue in this.Values) { @@ -244,7 +245,7 @@ internal IExifValue GetValueInternal(ExifTag tag) /// /// The tag of the exif value. /// The value. - internal void SetValueInternal(ExifTag tag, object value) + internal void SetValueInternal(ExifTag tag, object? value) { foreach (IExifValue exifValue in this.Values) { @@ -255,14 +256,14 @@ internal void SetValueInternal(ExifTag tag, object value) } } - ExifValue newExifValue = ExifValues.Create(tag); + ExifValue? newExifValue = ExifValues.Create(tag); if (newExifValue is null) { throw new NotSupportedException(); } newExifValue.TrySetValue(value); - this.values.Add(newExifValue); + this.values!.Add(newExifValue); } /// @@ -277,7 +278,7 @@ internal void Sync(ImageMetadata metadata) private void SyncResolution(ExifTag tag, double resolution) { - IExifValue value = this.GetValue(tag); + IExifValue? value = this.GetValue(tag); if (value is null) { @@ -293,6 +294,7 @@ private void SyncResolution(ExifTag tag, double resolution) this.SetValue(tag, newResolution); } + [MemberNotNull(nameof(values))] private void InitializeValues() { if (this.values != null) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs index 09daf601d0..7b989c8d8a 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs @@ -19,7 +19,7 @@ public ExifReader(byte[] exifData) { } - public ExifReader(byte[] exifData, MemoryAllocator allocator) + public ExifReader(byte[] exifData, MemoryAllocator? allocator) : base(new MemoryStream(exifData ?? throw new ArgumentNullException(nameof(exifData))), allocator) { } @@ -89,13 +89,13 @@ internal abstract class BaseExifReader private readonly byte[] buf4 = new byte[4]; private readonly byte[] buf2 = new byte[2]; - private readonly MemoryAllocator allocator; + private readonly MemoryAllocator? allocator; private readonly Stream data; - private List invalidTags; + private List? invalidTags; - private List subIfds; + private List? subIfds; - protected BaseExifReader(Stream stream, MemoryAllocator allocator) + protected BaseExifReader(Stream stream, MemoryAllocator? allocator) { this.data = stream ?? throw new ArgumentNullException(nameof(stream)); this.allocator = allocator; @@ -218,7 +218,7 @@ protected void ReadBigValue(IList values, (ulong Offset, ExifDataTyp this.Seek(tag.Offset); if (this.TryReadSpan(buffer)) { - object value = this.ConvertValue(tag.DataType, buffer, tag.NumberOfComponents > 1 || tag.Exif.IsArray); + object? value = this.ConvertValue(tag.DataType, buffer, tag.NumberOfComponents > 1 || tag.Exif.IsArray); this.Add(values, tag.Exif, value); } } @@ -254,7 +254,7 @@ private static string ConvertToString(Encoding encoding, ReadOnlySpan buff private static byte ConvertToByte(ReadOnlySpan buffer) => buffer[0]; - private object ConvertValue(ExifDataType dataType, ReadOnlySpan buffer, bool isArray) + private object? ConvertValue(ExifDataType dataType, ReadOnlySpan buffer, bool isArray) { if (buffer.Length == 0) { @@ -389,7 +389,7 @@ private void ReadValue(List values, Span offsetBuffer) numberOfComponents = 4 / ExifDataTypes.GetSize(dataType); } - ExifValue exifValue = ExifValues.Create(tag) ?? ExifValues.Create(tag, dataType, numberOfComponents); + ExifValue? exifValue = ExifValues.Create(tag) ?? ExifValues.Create(tag, dataType, numberOfComponents); if (exifValue is null) { @@ -413,7 +413,7 @@ private void ReadValue(List values, Span offsetBuffer) } else { - object value = this.ConvertValue(dataType, offsetBuffer[..(int)size], numberOfComponents > 1 || exifValue.IsArray); + object? value = this.ConvertValue(dataType, offsetBuffer[..(int)size], numberOfComponents > 1 || exifValue.IsArray); this.Add(values, exifValue, value); } } @@ -442,7 +442,7 @@ private void ReadValue64(List values, Span offsetBuffer) numberOfComponents = 8 / ExifDataTypes.GetSize(dataType); } - ExifValue exifValue = tag switch + ExifValue? exifValue = tag switch { ExifTagValue.StripOffsets => new ExifLong8Array(ExifTagValue.StripOffsets), ExifTagValue.StripByteCounts => new ExifLong8Array(ExifTagValue.StripByteCounts), @@ -470,12 +470,12 @@ private void ReadValue64(List values, Span offsetBuffer) } else { - object value = this.ConvertValue(dataType, offsetBuffer[..(int)size], numberOfComponents > 1 || exifValue.IsArray); + object? value = this.ConvertValue(dataType, offsetBuffer[..(int)size], numberOfComponents > 1 || exifValue.IsArray); this.Add(values, exifValue, value); } } - private void Add(IList values, IExifValue exif, object value) + private void Add(IList values, IExifValue exif, object? value) { if (!exif.TrySetValue(value)) { @@ -509,7 +509,7 @@ private void Add(IList values, IExifValue exif, object value) private void AddInvalidTag(ExifTag tag) => (this.invalidTags ??= new List()).Add(tag); - private void AddSubIfd(object val) + private void AddSubIfd(object? val) => (this.subIfds ??= new List()).Add(Convert.ToUInt64(val, CultureInfo.InvariantCulture)); private void Seek(ulong pos) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs index b3957dfb2a..5bafd89d09 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs @@ -28,10 +28,10 @@ public ExifTagDescriptionAttribute(object value, string description) /// /// The . /// - public static string GetDescription(ExifTag tag, object value) + public static string? GetDescription(ExifTag tag, object value) { var tagValue = (ExifTagValue)(ushort)tag; - FieldInfo field = typeof(ExifTagValue).GetField(tagValue.ToString(), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); + FieldInfo? field = typeof(ExifTagValue).GetField(tagValue.ToString(), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (field is null) { @@ -40,11 +40,11 @@ public static string GetDescription(ExifTag tag, object value) foreach (CustomAttributeData customAttribute in field.CustomAttributes) { - object attributeValue = customAttribute.ConstructorArguments[0].Value; + object? attributeValue = customAttribute.ConstructorArguments[0].Value; if (Equals(attributeValue, value)) { - return (string)customAttribute.ConstructorArguments[1].Value; + return (string?)customAttribute.ConstructorArguments[1].Value; } } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs index fc0a50dc74..7de85ef4e9 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs @@ -15,7 +15,7 @@ internal sealed class ExifWriter /// private readonly ExifParts allowedParts; private readonly IList values; - private List dataOffsets; + private List? dataOffsets; private readonly List ifdValues; private readonly List exifValues; private readonly List gpsValues; @@ -44,8 +44,8 @@ public byte[] GetData() { const uint startIndex = 0; - IExifValue exifOffset = GetOffsetValue(this.ifdValues, this.exifValues, ExifTag.SubIFDOffset); - IExifValue gpsOffset = GetOffsetValue(this.ifdValues, this.gpsValues, ExifTag.GPSIFDOffset); + IExifValue? exifOffset = GetOffsetValue(this.ifdValues, this.exifValues, ExifTag.SubIFDOffset); + IExifValue? gpsOffset = GetOffsetValue(this.ifdValues, this.gpsValues, ExifTag.GPSIFDOffset); uint ifdLength = GetLength(this.ifdValues); uint exifLength = GetLength(this.exifValues); @@ -159,7 +159,7 @@ private static int WriteInt32(int value, Span destination, int offset) return offset + 4; } - private static IExifValue GetOffsetValue(List ifdValues, List values, ExifTag offset) + private static IExifValue? GetOffsetValue(List ifdValues, List values, ExifTag offset) { int index = -1; @@ -178,8 +178,8 @@ private static IExifValue GetOffsetValue(List ifdValues, List GetPartValues(ExifParts part) private static bool HasValue(IExifValue exifValue) { - object value = exifValue.GetValue(); + object? value = exifValue.GetValue(); if (value is null) { return false; @@ -269,11 +269,11 @@ private static uint GetLength(IList values) internal static uint GetNumberOfComponents(IExifValue exifValue) { - object value = exifValue.GetValue(); + object? value = exifValue.GetValue(); if (ExifUcs2StringHelpers.IsUcs2Tag((ExifTagValue)(ushort)exifValue.Tag)) { - return (uint)ExifUcs2StringHelpers.Ucs2Encoding.GetByteCount((string)value); + return (uint)ExifUcs2StringHelpers.Ucs2Encoding.GetByteCount((string)value!); } if (value is EncodedString encodedString) @@ -283,7 +283,7 @@ internal static uint GetNumberOfComponents(IExifValue exifValue) if (exifValue.DataType == ExifDataType.Ascii) { - return (uint)ExifConstants.DefaultEncoding.GetByteCount((string)value) + 1; + return (uint)ExifConstants.DefaultEncoding.GetByteCount((string)value!) + 1; } if (value is Array arrayValue) @@ -297,7 +297,7 @@ internal static uint GetNumberOfComponents(IExifValue exifValue) private static int WriteArray(IExifValue value, Span destination, int offset) { int newOffset = offset; - foreach (object obj in (Array)value.GetValue()) + foreach (object obj in (Array)value.GetValue()!) { newOffset = WriteValue(value.DataType, obj, destination, newOffset); } @@ -307,7 +307,7 @@ private static int WriteArray(IExifValue value, Span destination, int offs private int WriteData(uint startIndex, List values, Span destination, int offset) { - if (this.dataOffsets.Count == 0) + if (this.dataOffsets?.Count == 0) { return offset; } @@ -319,7 +319,7 @@ private int WriteData(uint startIndex, List values, Span desti { if (GetLength(value) > 4) { - WriteUInt32((uint)(newOffset - startIndex), destination, this.dataOffsets[i++]); + WriteUInt32((uint)(newOffset - startIndex), destination, this.dataOffsets![i++]); newOffset = WriteValue(value, destination, newOffset); } } @@ -427,11 +427,11 @@ private static int WriteValue(ExifDataType dataType, object value, Span de internal static int WriteValue(IExifValue exifValue, Span destination, int offset) { - object value = exifValue.GetValue(); + object? value = exifValue.GetValue(); if (ExifUcs2StringHelpers.IsUcs2Tag((ExifTagValue)(ushort)exifValue.Tag)) { - return offset + ExifUcs2StringHelpers.Write((string)value, destination[offset..]); + return offset + ExifUcs2StringHelpers.Write((string)value!, destination[offset..]); } else if (value is EncodedString encodedString) { @@ -443,6 +443,6 @@ internal static int WriteValue(IExifValue exifValue, Span destination, int return WriteArray(exifValue, destination, offset); } - return WriteValue(exifValue.DataType, value, destination, offset); + return WriteValue(exifValue.DataType, value!, destination, offset); } } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.cs b/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.cs index d6e1b7e561..ea0b8060d5 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.cs @@ -33,7 +33,7 @@ public abstract partial class ExifTag : IEquatable public static bool operator !=(ExifTag left, ExifTag right) => !Equals(left, right); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is ExifTag value) { @@ -44,7 +44,7 @@ public override bool Equals(object obj) } /// - public bool Equals(ExifTag other) + public bool Equals(ExifTag? other) { if (other is null) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs index 3fc8e13b7f..cd5d1dc626 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs @@ -100,7 +100,7 @@ public enum CharacterCode public static bool operator !=(EncodedString left, EncodedString right) => !(left == right); /// - public override bool Equals(object obj) => obj is EncodedString other && this.Equals(other); + public override bool Equals(object? obj) => obj is EncodedString other && this.Equals(other); /// public bool Equals(EncodedString other) => this.Text == other.Text && this.Code == other.Code; diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifArrayValue{TValueType}.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifArrayValue{TValueType}.cs index 2405f24ad8..64b8d23137 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifArrayValue{TValueType}.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifArrayValue{TValueType}.cs @@ -22,11 +22,11 @@ internal ExifArrayValue(ExifArrayValue value) public override bool IsArray => true; - public TValueType[] Value { get; set; } + public TValueType[]? Value { get; set; } - public override object GetValue() => this.Value; + public override object? GetValue() => this.Value; - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (value is null) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByte.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByte.cs index 910da27da0..eb69c43897 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByte.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByte.cs @@ -20,7 +20,7 @@ private ExifByte(ExifByte value) protected override string StringValue => this.Value.ToString("X2", CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByteArray.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByteArray.cs index 532d69395c..4320cb5e82 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByteArray.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByteArray.cs @@ -16,7 +16,7 @@ private ExifByteArray(ExifByteArray value) public override ExifDataType DataType { get; } - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifDouble.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifDouble.cs index e8a2699d82..1d24a7dfb7 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifDouble.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifDouble.cs @@ -26,7 +26,7 @@ private ExifDouble(ExifDouble value) protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifEncodedString.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifEncodedString.cs index 317f8d7716..cce7cf3e89 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifEncodedString.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifEncodedString.cs @@ -24,7 +24,7 @@ private ExifEncodedString(ExifEncodedString value) protected override string StringValue => this.Value.Text; - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifFloat.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifFloat.cs index 904a9ee02c..bfe5871e8a 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifFloat.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifFloat.cs @@ -21,7 +21,7 @@ private ExifFloat(ExifFloat value) protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong.cs index 4fb5e8092b..8f185ea363 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong.cs @@ -26,7 +26,7 @@ private ExifLong(ExifLong value) protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong8.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong8.cs index 9f25031446..13feb6ad6e 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong8.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong8.cs @@ -26,7 +26,7 @@ private ExifLong8(ExifLong8 value) protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong8Array.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong8Array.cs index ff48fc7741..b7756e62bd 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong8Array.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifLong8Array.cs @@ -34,7 +34,7 @@ public override ExifDataType DataType } } - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumber.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumber.cs index 780f389ab4..a78107317c 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumber.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumber.cs @@ -32,7 +32,7 @@ public override ExifDataType DataType protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumberArray.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumberArray.cs index 6b5aafbad5..1162c25ea9 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumberArray.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumberArray.cs @@ -34,7 +34,7 @@ public override ExifDataType DataType } } - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRational.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRational.cs index 958c6f8342..c25f0f5dc1 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRational.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRational.cs @@ -26,7 +26,7 @@ private ExifRational(ExifRational value) protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRationalArray.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRationalArray.cs index 0114a7fbda..ac6453edc7 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRationalArray.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRationalArray.cs @@ -22,7 +22,7 @@ private ExifRationalArray(ExifRationalArray value) public override ExifDataType DataType => ExifDataType.Rational; - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifShort.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifShort.cs index 68932b3b87..d35b21422b 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifShort.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifShort.cs @@ -26,7 +26,7 @@ private ExifShort(ExifShort value) protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifShortArray.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifShortArray.cs index 42c919bb7d..a205e77dee 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifShortArray.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifShortArray.cs @@ -22,7 +22,7 @@ private ExifShortArray(ExifShortArray value) public override ExifDataType DataType => ExifDataType.Short; - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedByte.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedByte.cs index c9bf7a820f..95a239b70d 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedByte.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedByte.cs @@ -21,7 +21,7 @@ private ExifSignedByte(ExifSignedByte value) protected override string StringValue => this.Value.ToString("X2", CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShort.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShort.cs index 72fd0b65a1..52e17e63ec 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShort.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShort.cs @@ -19,9 +19,9 @@ private ExifSignedShort(ExifSignedShort value) public override ExifDataType DataType => ExifDataType.SignedShort; - protected override string StringValue => this.Value.ToString(CultureInfo.InvariantCulture); + protected override string? StringValue => this.Value.ToString(CultureInfo.InvariantCulture); - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShortArray.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShortArray.cs index 464105b3be..8023fb8bca 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShortArray.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShortArray.cs @@ -17,7 +17,7 @@ private ExifSignedShortArray(ExifSignedShortArray value) public override ExifDataType DataType => ExifDataType.SignedShort; - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifString.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifString.cs index 1eb712bcac..562583daee 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifString.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifString.cs @@ -24,9 +24,9 @@ private ExifString(ExifString value) public override ExifDataType DataType => ExifDataType.Ascii; - protected override string StringValue => this.Value; + protected override string? StringValue => this.Value; - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifUcs2String.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifUcs2String.cs index 9e7c96dac9..88c3e816ec 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifUcs2String.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifUcs2String.cs @@ -22,11 +22,11 @@ private ExifUcs2String(ExifUcs2String value) public override ExifDataType DataType => ExifDataType.Byte; - protected override string StringValue => this.Value; + protected override string? StringValue => this.Value; - public override object GetValue() => this.Value; + public override object? GetValue() => this.Value; - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (base.TrySetValue(value)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue.cs index 59ee815376..2352a3705b 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue.cs @@ -27,7 +27,7 @@ internal ExifValue(ExifValue other) else { // All array types are value types so Clone() is sufficient here. - var array = (Array)other.GetValue(); + var array = (Array)other.GetValue()!; this.TrySetValue(array?.Clone()); } } @@ -42,7 +42,7 @@ internal ExifValue(ExifValue other) public static bool operator !=(ExifValue left, ExifTag right) => !Equals(left, right); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is null) { @@ -68,14 +68,14 @@ public override bool Equals(object obj) } [MethodImpl(InliningOptions.ShortMethod)] - public bool Equals(ExifTag other) => this.Tag.Equals(other); + public bool Equals(ExifTag? other) => this.Tag.Equals(other); [MethodImpl(InliningOptions.ShortMethod)] public override int GetHashCode() => HashCode.Combine(this.Tag, this.GetValue()); - public abstract object GetValue(); + public abstract object? GetValue(); - public abstract bool TrySetValue(object value); + public abstract bool TrySetValue(object? value); public abstract IExifValue DeepClone(); } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs index 93720fbe94..68c4391949 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs @@ -5,13 +5,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif; internal static partial class ExifValues { - public static ExifValue Create(ExifTagValue tag) => (ExifValue)CreateValue(tag); + public static ExifValue? Create(ExifTagValue tag) => (ExifValue?)CreateValue(tag); - public static ExifValue Create(ExifTag tag) => (ExifValue)CreateValue((ExifTagValue)(ushort)tag); + public static ExifValue? Create(ExifTag tag) => (ExifValue?)CreateValue((ExifTagValue)(ushort)tag); - public static ExifValue Create(ExifTagValue tag, ExifDataType dataType, ulong numberOfComponents) => Create(tag, dataType, numberOfComponents != 1); + public static ExifValue? Create(ExifTagValue tag, ExifDataType dataType, ulong numberOfComponents) => Create(tag, dataType, numberOfComponents != 1); - public static ExifValue Create(ExifTagValue tag, ExifDataType dataType, bool isArray) + public static ExifValue? Create(ExifTagValue tag, ExifDataType dataType, bool isArray) { switch (dataType) { @@ -48,7 +48,7 @@ public static ExifValue Create(ExifTagValue tag, ExifDataType dataType, bool isA } } - private static object CreateValue(ExifTagValue tag) + private static object? CreateValue(ExifTagValue tag) { switch (tag) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs index 2dcf1d4363..f4ac1fc1ba 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs @@ -20,16 +20,16 @@ internal ExifValue(ExifValue value) { } - public TValueType Value { get; set; } + public TValueType? Value { get; set; } /// /// Gets the value of the current instance as a string. /// - protected abstract string StringValue { get; } + protected abstract string? StringValue { get; } - public override object GetValue() => this.Value; + public override object? GetValue() => this.Value; - public override bool TrySetValue(object value) + public override bool TrySetValue(object? value) { if (value is null) { @@ -48,14 +48,14 @@ public override bool TrySetValue(object value) return false; } - public override string ToString() + public override string? ToString() { if (this.Value == null) { return null; } - string description = ExifTagDescriptionAttribute.GetDescription(this.Tag, this.Value); + string? description = ExifTagDescriptionAttribute.GetDescription(this.Tag, this.Value); return description ?? this.StringValue; } } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/IExifValue.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/IExifValue.cs index a68cf14d43..c5b1574f30 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/IExifValue.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/IExifValue.cs @@ -27,12 +27,12 @@ public interface IExifValue : IDeepCloneable /// Gets the value of this exif value. /// /// The value of this exif value. - object GetValue(); + object? GetValue(); /// /// Sets the value of this exif value. /// /// The value of this exif value. /// A value indicating whether the value could be set. - bool TrySetValue(object value); + bool TrySetValue(object? value); } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/IExifValue{TValueType}.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/IExifValue{TValueType}.cs index d49e80ea00..ec84b78f71 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/IExifValue{TValueType}.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/IExifValue{TValueType}.cs @@ -12,5 +12,5 @@ public interface IExifValue : IExifValue /// /// Gets or sets the value. /// - TValueType Value { get; set; } + TValueType? Value { get; set; } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccCurveSegment.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccCurveSegment.cs index 9937f156fd..cebc58a259 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccCurveSegment.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccCurveSegment.cs @@ -21,7 +21,7 @@ protected IccCurveSegment(IccCurveSegmentSignature signature) public IccCurveSegmentSignature Signature { get; } /// - public virtual bool Equals(IccCurveSegment other) + public virtual bool Equals(IccCurveSegment? other) { if (other is null) { @@ -37,7 +37,7 @@ public virtual bool Equals(IccCurveSegment other) } /// - public override bool Equals(object obj) => this.Equals(obj as IccCurveSegment); + public override bool Equals(object? obj) => this.Equals(obj as IccCurveSegment); /// public override int GetHashCode() => this.Signature.GetHashCode(); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccFormulaCurveElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccFormulaCurveElement.cs index ad442671d1..068a4d11a1 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccFormulaCurveElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccFormulaCurveElement.cs @@ -66,7 +66,7 @@ public IccFormulaCurveElement(IccFormulaCurveType type, float gamma, float a, fl public float E { get; } /// - public override bool Equals(IccCurveSegment other) + public override bool Equals(IccCurveSegment? other) { if (base.Equals(other) && other is IccFormulaCurveElement segment) { @@ -83,10 +83,10 @@ public override bool Equals(IccCurveSegment other) } /// - public bool Equals(IccFormulaCurveElement other) => this.Equals((IccCurveSegment)other); + public bool Equals(IccFormulaCurveElement? other) => this.Equals((IccCurveSegment?)other); /// - public override bool Equals(object obj) => this.Equals(obj as IccFormulaCurveElement); + public override bool Equals(object? obj) => this.Equals(obj as IccFormulaCurveElement); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccOneDimensionalCurve.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccOneDimensionalCurve.cs index fc3c9030ee..30935ebbe5 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccOneDimensionalCurve.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccOneDimensionalCurve.cs @@ -36,7 +36,7 @@ public IccOneDimensionalCurve(float[] breakPoints, IccCurveSegment[] segments) public IccCurveSegment[] Segments { get; } /// - public bool Equals(IccOneDimensionalCurve other) + public bool Equals(IccOneDimensionalCurve? other) { if (other is null) { @@ -53,7 +53,7 @@ public bool Equals(IccOneDimensionalCurve other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => this.Equals(obj as IccOneDimensionalCurve); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccParametricCurve.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccParametricCurve.cs index 9ce1876269..0f1f4511d3 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccParametricCurve.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccParametricCurve.cs @@ -121,7 +121,7 @@ private IccParametricCurve(IccParametricCurveType type, float g, float a, float public float F { get; } /// - public bool Equals(IccParametricCurve other) + public bool Equals(IccParametricCurve? other) { if (other is null) { @@ -144,7 +144,7 @@ public bool Equals(IccParametricCurve other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccParametricCurve other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccResponseCurve.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccResponseCurve.cs index 969e359591..45139aae2a 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccResponseCurve.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccResponseCurve.cs @@ -45,7 +45,7 @@ public IccResponseCurve(IccCurveMeasurementEncodings curveType, Vector3[] xyzVal public IccResponseNumber[][] ResponseArrays { get; } /// - public bool Equals(IccResponseCurve other) + public bool Equals(IccResponseCurve? other) { if (other is null) { @@ -63,7 +63,7 @@ public bool Equals(IccResponseCurve other) } /// - public override bool Equals(object obj) => obj is IccResponseCurve other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccResponseCurve other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccSampledCurveElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccSampledCurveElement.cs index 3fcde5ad2d..4a66b58c13 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccSampledCurveElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Curves/IccSampledCurveElement.cs @@ -27,7 +27,7 @@ public IccSampledCurveElement(float[] curveEntries) public float[] CurveEntries { get; } /// - public override bool Equals(IccCurveSegment other) + public override bool Equals(IccCurveSegment? other) { if (base.Equals(other) && other is IccSampledCurveElement segment) { @@ -38,11 +38,11 @@ public override bool Equals(IccCurveSegment other) } /// - public bool Equals(IccSampledCurveElement other) - => this.Equals((IccCurveSegment)other); + public bool Equals(IccSampledCurveElement? other) + => this.Equals((IccCurveSegment?)other); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => this.Equals(obj as IccSampledCurveElement); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Lut.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Lut.cs index e88dd8d9e1..f11ded7ebe 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Lut.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.Lut.cs @@ -41,7 +41,7 @@ public IccLut ReadLut16(int count) /// If true, it's read as CLUTf32, /// else read as either CLUT8 or CLUT16 depending on embedded information /// The read CLUT - public IccClut ReadClut(int inChannelCount, int outChannelCount, bool isFloat) + public IccClut? ReadClut(int inChannelCount, int outChannelCount, bool isFloat) { // Grid-points are always 16 bytes long but only 0-inChCount are used var gridPointCount = new byte[inChannelCount]; @@ -73,7 +73,7 @@ public IccClut ReadClut(int inChannelCount, int outChannelCount, bool isFloat) /// Output channel count /// Grid point count for each CLUT channel /// The read CLUT8 - public IccClut ReadClut8(int inChannelCount, int outChannelCount, byte[] gridPointCount) + public IccClut? ReadClut8(int inChannelCount, int outChannelCount, byte[] gridPointCount) { int start = this.currentIndex; int length = 0; @@ -107,7 +107,7 @@ public IccClut ReadClut8(int inChannelCount, int outChannelCount, byte[] gridPoi /// Output channel count /// Grid point count for each CLUT channel /// The read CLUT16 - public IccClut ReadClut16(int inChannelCount, int outChannelCount, byte[] gridPointCount) + public IccClut? ReadClut16(int inChannelCount, int outChannelCount, byte[] gridPointCount) { int start = this.currentIndex; int length = 0; @@ -141,7 +141,7 @@ public IccClut ReadClut16(int inChannelCount, int outChannelCount, byte[] gridPo /// Output channel count /// Grid point count for each CLUT channel /// The read CLUTf32 - public IccClut ReadClutF32(int inChCount, int outChCount, byte[] gridPointCount) + public IccClut? ReadClutF32(int inChCount, int outChCount, byte[] gridPointCount) { int start = this.currentIndex; int length = 0; diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs index d5369e5fc4..8e6674f927 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs @@ -144,7 +144,7 @@ IccMultiLocalizedUnicodeTagDataEntry ReadText() case IccTypeSignature.MultiLocalizedUnicode: return this.ReadMultiLocalizedUnicodeTagDataEntry(); case IccTypeSignature.TextDescription: - return (IccMultiLocalizedUnicodeTagDataEntry)this.ReadTextDescriptionTagDataEntry(); + return (IccMultiLocalizedUnicodeTagDataEntry)this.ReadTextDescriptionTagDataEntry()!; default: throw new InvalidIccProfileException("Profile description can only have multi-localized Unicode or text description entries"); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs index 53b47d38bd..57190a72b0 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs @@ -271,7 +271,7 @@ public IccLut16TagDataEntry ReadLut16TagDataEntry() } // CLUT - IccClut clut = this.ReadClut16(inChCount, outChCount, gridPointCount); + IccClut? clut = this.ReadClut16(inChCount, outChCount, gridPointCount); // Output LUT var outValues = new IccLut[outChCount]; @@ -306,7 +306,7 @@ public IccLut8TagDataEntry ReadLut8TagDataEntry() } // CLUT - IccClut clut = this.ReadClut8(inChCount, outChCount, gridPointCount); + IccClut? clut = this.ReadClut8(inChCount, outChCount, gridPointCount); // Output LUT var outValues = new IccLut[outChCount]; @@ -336,12 +336,12 @@ public IccLutAToBTagDataEntry ReadLutAtoBTagDataEntry() uint clutOffset = this.ReadUInt32(); uint aCurveOffset = this.ReadUInt32(); - IccTagDataEntry[] bCurve = null; - IccTagDataEntry[] mCurve = null; - IccTagDataEntry[] aCurve = null; - IccClut clut = null; - float[,] matrix3x3 = null; - float[] matrix3x1 = null; + IccTagDataEntry[]? bCurve = null; + IccTagDataEntry[]? mCurve = null; + IccTagDataEntry[]? aCurve = null; + IccClut? clut = null; + float[,]? matrix3x3 = null; + float[]? matrix3x1 = null; if (bCurveOffset != 0) { @@ -395,12 +395,12 @@ public IccLutBToATagDataEntry ReadLutBtoATagDataEntry() uint clutOffset = this.ReadUInt32(); uint aCurveOffset = this.ReadUInt32(); - IccTagDataEntry[] bCurve = null; - IccTagDataEntry[] mCurve = null; - IccTagDataEntry[] aCurve = null; - IccClut clut = null; - float[,] matrix3x3 = null; - float[] matrix3x1 = null; + IccTagDataEntry[]? bCurve = null; + IccTagDataEntry[]? mCurve = null; + IccTagDataEntry[]? aCurve = null; + IccClut? clut = null; + float[,]? matrix3x3 = null; + float[]? matrix3x1 = null; if (bCurveOffset != 0) { @@ -484,7 +484,7 @@ public IccMultiLocalizedUnicodeTagDataEntry ReadMultiLocalizedUnicodeTagDataEntr return new IccMultiLocalizedUnicodeTagDataEntry(text); - CultureInfo ReadCulture(string language, string country) + CultureInfo ReadCulture(string language, string? country) { if (string.IsNullOrWhiteSpace(language)) { @@ -794,8 +794,8 @@ public IccXyzTagDataEntry ReadXyzTagDataEntry(uint size) /// The read entry public IccTextDescriptionTagDataEntry ReadTextDescriptionTagDataEntry() { - string unicodeValue, scriptcodeValue; - string asciiValue = unicodeValue = scriptcodeValue = null; + string? unicodeValue, scriptcodeValue; + string? asciiValue = unicodeValue = scriptcodeValue = null; int asciiCount = (int)this.ReadUInt32(); if (asciiCount > 0) diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElement.cs index 9be693ba22..27b02fd69f 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.MultiProcessElement.cs @@ -72,6 +72,6 @@ public int WriteMatrixProcessElement(IccMatrixProcessElement value) /// The number of bytes written public int WriteClutProcessElement(IccClutProcessElement value) { - return this.WriteClut(value.ClutValue); + return this.WriteClut(value.ClutValue!); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs index e1eebb749b..a668c61207 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs @@ -189,7 +189,7 @@ public int WriteAsciiString(string value) /// The desired length of the string (including potential null terminator) /// If True, there will be a \0 added at the end /// the number of bytes written - public int WriteAsciiString(string value, int length, bool ensureNullTerminator) + public int WriteAsciiString(string? value, int length, bool ensureNullTerminator) { if (length == 0) { diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs index 2b4fdd2391..c8610b086d 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs @@ -70,7 +70,7 @@ public int WriteTagDataEntry(IccTagDataEntry entry) IccTypeSignature.UcrBg => this.WriteUcrBgTagDataEntry((IccUcrBgTagDataEntry)entry), // Unsupported or unknown - _ => this.WriteUnknownTagDataEntry(entry as IccUnknownTagDataEntry), + _ => this.WriteUnknownTagDataEntry((entry as IccUnknownTagDataEntry)!), }; return count; } @@ -198,7 +198,7 @@ public int WriteLut16TagDataEntry(IccLut16TagDataEntry value) { int count = this.WriteByte((byte)value.InputValues.Length); count += this.WriteByte((byte)value.OutputValues.Length); - count += this.WriteByte(value.ClutValues.GridPointCount[0]); + count += this.WriteByte(value.ClutValues!.GridPointCount[0]); count += this.WriteEmpty(1); count += this.WriteMatrix(value.Matrix, false); @@ -230,7 +230,7 @@ public int WriteLut8TagDataEntry(IccLut8TagDataEntry value) { int count = this.WriteByte((byte)value.InputChannelCount); count += this.WriteByte((byte)value.OutputChannelCount); - count += this.WriteByte((byte)value.ClutValues.Values[0].Length); + count += this.WriteByte((byte)value.ClutValues!.Values[0].Length); count += this.WriteEmpty(1); count += this.WriteMatrix(value.Matrix, false); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs index e4403a47e2..3d5c7745d6 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; using System.Security.Cryptography; namespace SixLabors.ImageSharp.Metadata.Profiles.Icc; @@ -13,23 +14,23 @@ public sealed class IccProfile : IDeepCloneable /// /// The byte array to read the ICC profile from /// - private readonly byte[] data; + private readonly byte[]? data; /// /// The backing file for the property /// - private IccTagDataEntry[] entries; + private IccTagDataEntry[]? entries; /// /// ICC profile header /// - private IccProfileHeader header; + private IccProfileHeader? header; /// /// Initializes a new instance of the class. /// public IccProfile() - : this((byte[])null) + : this((byte[]?)null) { } @@ -37,7 +38,7 @@ public IccProfile() /// Initializes a new instance of the class. /// /// The raw ICC profile data - public IccProfile(byte[] data) => this.data = data; + public IccProfile(byte[]? data) => this.data = data; /// /// Initializes a new instance of the class. @@ -178,6 +179,7 @@ public byte[] ToByteArray() return IccWriter.Write(this); } + [MemberNotNull(nameof(header))] private void InitializeHeader() { if (this.header != null) @@ -195,6 +197,7 @@ private void InitializeHeader() this.header = IccReader.ReadHeader(this.data); } + [MemberNotNull(nameof(entries))] private void InitializeEntries() { if (this.entries != null) diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccProfileHeader.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccProfileHeader.cs index 665a1d9c28..9d1fc50b82 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/IccProfileHeader.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/IccProfileHeader.cs @@ -18,7 +18,7 @@ public sealed class IccProfileHeader /// /// Gets or sets the preferred CMM (Color Management Module) type. /// - public string CmmType { get; set; } + public string? CmmType { get; set; } /// /// Gets or sets the profiles version number. @@ -49,7 +49,7 @@ public sealed class IccProfileHeader /// Gets or sets the file signature. Should always be "acsp". /// Value will be ignored when writing a profile. /// - public string FileSignature { get; set; } + public string? FileSignature { get; set; } /// /// Gets or sets the primary platform this profile as created for @@ -90,7 +90,7 @@ public sealed class IccProfileHeader /// /// Gets or sets profile creator signature. /// - public string CreatorSignature { get; set; } + public string? CreatorSignature { get; set; } /// /// Gets or sets the profile ID (hash). diff --git a/src/ImageSharp/Metadata/Profiles/ICC/IccTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/IccTagDataEntry.cs index 56d620ec32..12228f3f58 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/IccTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/IccTagDataEntry.cs @@ -40,13 +40,13 @@ protected IccTagDataEntry(IccTypeSignature signature, IccProfileTag tagSignature public IccProfileTag TagSignature { get; set; } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccTagDataEntry entry && this.Equals(entry); } /// - public virtual bool Equals(IccTagDataEntry other) + public virtual bool Equals(IccTagDataEntry? other) { if (other is null) { diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs index 847f881aed..e9ca7277b2 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccBAcsProcessElement.cs @@ -19,10 +19,10 @@ public IccBAcsProcessElement(int inChannelCount, int outChannelCount) } /// - public bool Equals(IccBAcsProcessElement other) => base.Equals(other); + public bool Equals(IccBAcsProcessElement? other) => base.Equals(other); /// - public override bool Equals(object obj) => this.Equals(obj as IccBAcsProcessElement); + public override bool Equals(object? obj) => this.Equals(obj as IccBAcsProcessElement); /// public override int GetHashCode() => base.GetHashCode(); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs index 1e8dd3d948..54bb6baefd 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccClutProcessElement.cs @@ -12,31 +12,31 @@ internal sealed class IccClutProcessElement : IccMultiProcessElement, IEquatable /// Initializes a new instance of the class. /// /// The color lookup table of this element - public IccClutProcessElement(IccClut clutValue) + public IccClutProcessElement(IccClut? clutValue) : base(IccMultiProcessElementSignature.Clut, clutValue?.InputChannelCount ?? 1, clutValue?.OutputChannelCount ?? 1) => this.ClutValue = clutValue ?? throw new ArgumentNullException(nameof(clutValue)); /// /// Gets the color lookup table of this element /// - public IccClut ClutValue { get; } + public IccClut? ClutValue { get; } /// - public override bool Equals(IccMultiProcessElement other) + public override bool Equals(IccMultiProcessElement? other) { if (base.Equals(other) && other is IccClutProcessElement element) { - return this.ClutValue.Equals(element.ClutValue); + return this.ClutValue!.Equals(element.ClutValue); } return false; } /// - public bool Equals(IccClutProcessElement other) => this.Equals((IccMultiProcessElement)other); + public bool Equals(IccClutProcessElement? other) => this.Equals((IccMultiProcessElement?)other); /// - public override bool Equals(object obj) => this.Equals(obj as IccClutProcessElement); + public override bool Equals(object? obj) => this.Equals(obj as IccClutProcessElement); /// public override int GetHashCode() => base.GetHashCode(); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs index ee6b0445e3..a90ceb8a6f 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccCurveSetProcessElement.cs @@ -22,7 +22,7 @@ public IccCurveSetProcessElement(IccOneDimensionalCurve[] curves) public IccOneDimensionalCurve[] Curves { get; } /// - public override bool Equals(IccMultiProcessElement other) + public override bool Equals(IccMultiProcessElement? other) { if (base.Equals(other) && other is IccCurveSetProcessElement element) { @@ -33,10 +33,10 @@ public override bool Equals(IccMultiProcessElement other) } /// - public bool Equals(IccCurveSetProcessElement other) => this.Equals((IccMultiProcessElement)other); + public bool Equals(IccCurveSetProcessElement? other) => this.Equals((IccMultiProcessElement?)other); /// - public override bool Equals(object obj) => this.Equals(obj as IccCurveSetProcessElement); + public override bool Equals(object? obj) => this.Equals(obj as IccCurveSetProcessElement); /// public override int GetHashCode() => base.GetHashCode(); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs index f7dbf25930..99c27f2bb9 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccEAcsProcessElement.cs @@ -19,9 +19,9 @@ public IccEAcsProcessElement(int inChannelCount, int outChannelCount) } /// - public bool Equals(IccEAcsProcessElement other) => base.Equals(other); + public bool Equals(IccEAcsProcessElement? other) => base.Equals(other); - public override bool Equals(object obj) => this.Equals(obj as IccEAcsProcessElement); + public override bool Equals(object? obj) => this.Equals(obj as IccEAcsProcessElement); /// public override int GetHashCode() => base.GetHashCode(); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs index 8d973e5f02..4c2923bce2 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs @@ -37,7 +37,7 @@ public IccMatrixProcessElement(float[,] matrixIxO, float[] matrixOx1) public float[] MatrixOx1 { get; } /// - public override bool Equals(IccMultiProcessElement other) + public override bool Equals(IccMultiProcessElement? other) { if (base.Equals(other) && other is IccMatrixProcessElement element) { @@ -49,11 +49,11 @@ public override bool Equals(IccMultiProcessElement other) } /// - public bool Equals(IccMatrixProcessElement other) - => this.Equals((IccMultiProcessElement)other); + public bool Equals(IccMatrixProcessElement? other) + => this.Equals((IccMultiProcessElement?)other); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => this.Equals(obj as IccMatrixProcessElement); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs index 57a0536fd1..1699271282 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMultiProcessElement.cs @@ -40,7 +40,7 @@ protected IccMultiProcessElement(IccMultiProcessElementSignature signature, int public int OutputChannelCount { get; } /// - public virtual bool Equals(IccMultiProcessElement other) + public virtual bool Equals(IccMultiProcessElement? other) { if (other is null) { @@ -57,7 +57,7 @@ public virtual bool Equals(IccMultiProcessElement other) && this.OutputChannelCount == other.OutputChannelCount; } - public override bool Equals(object obj) => this.Equals(obj as IccMultiProcessElement); + public override bool Equals(object? obj) => this.Equals(obj as IccMultiProcessElement); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs index aa90213a82..cc44762919 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs @@ -77,10 +77,10 @@ private IccChromaticityTagDataEntry(IccColorantEncoding colorantType, double[][] public double[][] ChannelValues { get; } /// - public override bool Equals(IccTagDataEntry other) => other is IccChromaticityTagDataEntry entry && this.Equals(entry); + public override bool Equals(IccTagDataEntry? other) => other is IccChromaticityTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccChromaticityTagDataEntry other) + public bool Equals(IccChromaticityTagDataEntry? other) { if (other is null) { @@ -96,7 +96,7 @@ public bool Equals(IccChromaticityTagDataEntry other) } /// - public override bool Equals(object obj) => obj is IccChromaticityTagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccChromaticityTagDataEntry other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs index 6f2a4480a9..f5d15897bf 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs @@ -38,13 +38,13 @@ public IccColorantOrderTagDataEntry(byte[] colorantNumber, IccProfileTag tagSign public byte[] ColorantNumber { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccColorantOrderTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccColorantOrderTagDataEntry other) + public bool Equals(IccColorantOrderTagDataEntry? other) { if (other is null) { @@ -60,7 +60,7 @@ public bool Equals(IccColorantOrderTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccColorantOrderTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs index 0c64cfc67c..92b353067e 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs @@ -39,10 +39,10 @@ public IccColorantTableTagDataEntry(IccColorantTableEntry[] colorantData, IccPro public IccColorantTableEntry[] ColorantData { get; } /// - public override bool Equals(IccTagDataEntry other) => other is IccColorantTableTagDataEntry entry && this.Equals(entry); + public override bool Equals(IccTagDataEntry? other) => other is IccColorantTableTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccColorantTableTagDataEntry other) + public bool Equals(IccColorantTableTagDataEntry? other) { if (other is null) { @@ -58,7 +58,7 @@ public bool Equals(IccColorantTableTagDataEntry other) } /// - public override bool Equals(object obj) => obj is IccColorantTableTagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccColorantTableTagDataEntry other && this.Equals(other); /// public override int GetHashCode() => HashCode.Combine(this.Signature, this.ColorantData); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs index 403c5c57c7..75176057d9 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs @@ -84,11 +84,11 @@ public IccCrdInfoTagDataEntry( public string RenderingIntent3Crd { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccCrdInfoTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccCrdInfoTagDataEntry other) + public bool Equals(IccCrdInfoTagDataEntry? other) { if (other is null) { @@ -109,7 +109,7 @@ public bool Equals(IccCrdInfoTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccCrdInfoTagDataEntry other && this.Equals(other); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs index 75f4cd52d3..5605d92559 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs @@ -86,13 +86,13 @@ public IccCurveTagDataEntry(float[] curveData, IccProfileTag tagSignature) public bool IsGamma => this.CurveData.Length == 1; /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccCurveTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccCurveTagDataEntry other) + public bool Equals(IccCurveTagDataEntry? other) { if (other is null) { @@ -108,7 +108,7 @@ public bool Equals(IccCurveTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccCurveTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs index 89af5286fe..3d83ccfee0 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs @@ -57,14 +57,14 @@ public IccDataTagDataEntry(byte[] data, bool isAscii, IccProfileTag tagSignature /// Gets the decoded as 7bit ASCII. /// If is false, returns null /// - public string AsciiString => this.IsAscii ? Encoding.ASCII.GetString(this.Data, 0, this.Data.Length) : null; + public string? AsciiString => this.IsAscii ? Encoding.ASCII.GetString(this.Data, 0, this.Data.Length) : null; /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccDataTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccDataTagDataEntry other) + public bool Equals(IccDataTagDataEntry? other) { if (other is null) { @@ -80,7 +80,7 @@ public bool Equals(IccDataTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccDataTagDataEntry other && this.Equals(other); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs index 9763da73c7..cd3fdcd1b1 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs @@ -34,13 +34,13 @@ public IccDateTimeTagDataEntry(DateTime value, IccProfileTag tagSignature) public DateTime Value { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccDateTimeTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccDateTimeTagDataEntry other) + public bool Equals(IccDateTimeTagDataEntry? other) { if (other is null) { @@ -56,7 +56,7 @@ public bool Equals(IccDateTimeTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccDateTimeTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs index 8e8918d887..d72c382a7e 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs @@ -34,13 +34,13 @@ public IccFix16ArrayTagDataEntry(float[] data, IccProfileTag tagSignature) public float[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccFix16ArrayTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccFix16ArrayTagDataEntry other) + public bool Equals(IccFix16ArrayTagDataEntry? other) { if (other is null) { @@ -56,7 +56,7 @@ public bool Equals(IccFix16ArrayTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccFix16ArrayTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs index aedecfdac3..9e9280e6fe 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs @@ -24,7 +24,7 @@ internal sealed class IccLut16TagDataEntry : IccTagDataEntry, IEquatableInput LUT /// CLUT /// Output LUT - public IccLut16TagDataEntry(IccLut[] inputValues, IccClut clutValues, IccLut[] outputValues) + public IccLut16TagDataEntry(IccLut[] inputValues, IccClut? clutValues, IccLut[] outputValues) : this(IdentityMatrix, inputValues, clutValues, outputValues, IccProfileTag.Unknown) { } @@ -36,7 +36,7 @@ public IccLut16TagDataEntry(IccLut[] inputValues, IccClut clutValues, IccLut[] o /// CLUT /// Output LUT /// Tag Signature - public IccLut16TagDataEntry(IccLut[] inputValues, IccClut clutValues, IccLut[] outputValues, IccProfileTag tagSignature) + public IccLut16TagDataEntry(IccLut[] inputValues, IccClut? clutValues, IccLut[] outputValues, IccProfileTag tagSignature) : this(IdentityMatrix, inputValues, clutValues, outputValues, tagSignature) { } @@ -48,7 +48,7 @@ public IccLut16TagDataEntry(IccLut[] inputValues, IccClut clutValues, IccLut[] o /// Input LUT /// CLUT /// Output LUT - public IccLut16TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutValues, IccLut[] outputValues) + public IccLut16TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut? clutValues, IccLut[] outputValues) : this(matrix, inputValues, clutValues, outputValues, IccProfileTag.Unknown) { } @@ -61,7 +61,7 @@ public IccLut16TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutV /// CLUT /// Output LUT /// Tag Signature - public IccLut16TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutValues, IccLut[] outputValues, IccProfileTag tagSignature) + public IccLut16TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut? clutValues, IccLut[] outputValues, IccProfileTag tagSignature) : base(IccTypeSignature.Lut16, tagSignature) { Guard.NotNull(matrix, nameof(matrix)); @@ -101,7 +101,7 @@ public IccLut16TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutV /// /// Gets the color lookup table /// - public IccClut ClutValues { get; } + public IccClut? ClutValues { get; } /// /// Gets the output lookup table @@ -109,10 +109,10 @@ public IccLut16TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutV public IccLut[] OutputValues { get; } /// - public override bool Equals(IccTagDataEntry other) => other is IccLut16TagDataEntry entry && this.Equals(entry); + public override bool Equals(IccTagDataEntry? other) => other is IccLut16TagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccLut16TagDataEntry other) + public bool Equals(IccLut16TagDataEntry? other) { if (other is null) { @@ -127,12 +127,12 @@ public bool Equals(IccLut16TagDataEntry other) return base.Equals(other) && this.Matrix.Equals(other.Matrix) && this.InputValues.AsSpan().SequenceEqual(other.InputValues) - && this.ClutValues.Equals(other.ClutValues) + && this.ClutValues!.Equals(other.ClutValues) && this.OutputValues.AsSpan().SequenceEqual(other.OutputValues); } /// - public override bool Equals(object obj) => obj is IccLut16TagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccLut16TagDataEntry other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs index 42e5670db4..0aef50e122 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs @@ -24,7 +24,7 @@ internal sealed class IccLut8TagDataEntry : IccTagDataEntry, IEquatableInput LUT /// CLUT /// Output LUT - public IccLut8TagDataEntry(IccLut[] inputValues, IccClut clutValues, IccLut[] outputValues) + public IccLut8TagDataEntry(IccLut[] inputValues, IccClut? clutValues, IccLut[] outputValues) : this(IdentityMatrix, inputValues, clutValues, outputValues, IccProfileTag.Unknown) { } @@ -36,7 +36,7 @@ public IccLut8TagDataEntry(IccLut[] inputValues, IccClut clutValues, IccLut[] ou /// CLUT /// Output LUT /// Tag Signature - public IccLut8TagDataEntry(IccLut[] inputValues, IccClut clutValues, IccLut[] outputValues, IccProfileTag tagSignature) + public IccLut8TagDataEntry(IccLut[] inputValues, IccClut? clutValues, IccLut[] outputValues, IccProfileTag tagSignature) : this(IdentityMatrix, inputValues, clutValues, outputValues, tagSignature) { } @@ -48,7 +48,7 @@ public IccLut8TagDataEntry(IccLut[] inputValues, IccClut clutValues, IccLut[] ou /// Input LUT /// CLUT /// Output LUT - public IccLut8TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutValues, IccLut[] outputValues) + public IccLut8TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut? clutValues, IccLut[] outputValues) : this(matrix, inputValues, clutValues, outputValues, IccProfileTag.Unknown) { } @@ -61,7 +61,7 @@ public IccLut8TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutVa /// CLUT /// Output LUT /// Tag Signature - public IccLut8TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutValues, IccLut[] outputValues, IccProfileTag tagSignature) + public IccLut8TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut? clutValues, IccLut[] outputValues, IccProfileTag tagSignature) : base(IccTypeSignature.Lut8, tagSignature) { Guard.NotNull(matrix, nameof(matrix)); @@ -104,7 +104,7 @@ public IccLut8TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutVa /// /// Gets the color lookup table /// - public IccClut ClutValues { get; } + public IccClut? ClutValues { get; } /// /// Gets the output lookup table @@ -112,10 +112,10 @@ public IccLut8TagDataEntry(float[,] matrix, IccLut[] inputValues, IccClut clutVa public IccLut[] OutputValues { get; } /// - public override bool Equals(IccTagDataEntry other) => other is IccLut8TagDataEntry entry && this.Equals(entry); + public override bool Equals(IccTagDataEntry? other) => other is IccLut8TagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccLut8TagDataEntry other) + public bool Equals(IccLut8TagDataEntry? other) { if (other is null) { @@ -130,12 +130,12 @@ public bool Equals(IccLut8TagDataEntry other) return base.Equals(other) && this.Matrix.Equals(other.Matrix) && this.InputValues.AsSpan().SequenceEqual(other.InputValues) - && this.ClutValues.Equals(other.ClutValues) + && this.ClutValues!.Equals(other.ClutValues) && this.OutputValues.AsSpan().SequenceEqual(other.OutputValues); } /// - public override bool Equals(object obj) => obj is IccLut8TagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccLut8TagDataEntry other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs index 823cd431cb..deeed6ff4d 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs @@ -21,12 +21,12 @@ internal sealed class IccLutAToBTagDataEntry : IccTagDataEntry, IEquatableCLUT /// A Curve public IccLutAToBTagDataEntry( - IccTagDataEntry[] curveB, - float[,] matrix3x3, - float[] matrix3x1, - IccTagDataEntry[] curveM, - IccClut clutValues, - IccTagDataEntry[] curveA) + IccTagDataEntry[]? curveB, + float[,]? matrix3x3, + float[]? matrix3x1, + IccTagDataEntry[]? curveM, + IccClut? clutValues, + IccTagDataEntry[]? curveA) : this(curveB, matrix3x3, matrix3x1, curveM, clutValues, curveA, IccProfileTag.Unknown) { } @@ -42,12 +42,12 @@ public IccLutAToBTagDataEntry( /// A Curve /// Tag Signature public IccLutAToBTagDataEntry( - IccTagDataEntry[] curveB, - float[,] matrix3x3, - float[] matrix3x1, - IccTagDataEntry[] curveM, - IccClut clutValues, - IccTagDataEntry[] curveA, + IccTagDataEntry[]? curveB, + float[,]? matrix3x3, + float[]? matrix3x1, + IccTagDataEntry[]? curveM, + IccClut? clutValues, + IccTagDataEntry[]? curveA, IccProfileTag tagSignature) : base(IccTypeSignature.LutAToB, tagSignature) { @@ -57,7 +57,7 @@ public IccLutAToBTagDataEntry( this.VerifyCurve(curveM, nameof(curveM)); this.Matrix3x3 = CreateMatrix3x3(matrix3x3); - this.Matrix3x1 = CreateMatrix3x1(matrix3x1); + this.Matrix3x1 = CreateMatrix3x1(matrix3x1!); this.CurveA = curveA; this.CurveB = curveB; this.CurveM = curveM; @@ -65,37 +65,37 @@ public IccLutAToBTagDataEntry( if (this.IsAClutMMatrixB()) { - Guard.IsTrue(this.CurveB.Length == 3, nameof(this.CurveB), $"{nameof(this.CurveB)} must have a length of three"); - Guard.IsTrue(this.CurveM.Length == 3, nameof(this.CurveM), $"{nameof(this.CurveM)} must have a length of three"); - Guard.MustBeBetweenOrEqualTo(this.CurveA.Length, 1, 15, nameof(this.CurveA)); + Guard.IsTrue(this.CurveB!.Length == 3, nameof(this.CurveB), $"{nameof(this.CurveB)} must have a length of three"); + Guard.IsTrue(this.CurveM!.Length == 3, nameof(this.CurveM), $"{nameof(this.CurveM)} must have a length of three"); + Guard.MustBeBetweenOrEqualTo(this.CurveA!.Length, 1, 15, nameof(this.CurveA)); - this.InputChannelCount = curveA.Length; + this.InputChannelCount = curveA!.Length; this.OutputChannelCount = 3; - Guard.IsTrue(this.InputChannelCount == clutValues.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); + Guard.IsTrue(this.InputChannelCount == clutValues!.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); Guard.IsTrue(this.OutputChannelCount == clutValues.OutputChannelCount, nameof(clutValues), "Output channel count does not match the CLUT size"); } else if (this.IsMMatrixB()) { - Guard.IsTrue(this.CurveB.Length == 3, nameof(this.CurveB), $"{nameof(this.CurveB)} must have a length of three"); - Guard.IsTrue(this.CurveM.Length == 3, nameof(this.CurveM), $"{nameof(this.CurveM)} must have a length of three"); + Guard.IsTrue(this.CurveB!.Length == 3, nameof(this.CurveB), $"{nameof(this.CurveB)} must have a length of three"); + Guard.IsTrue(this.CurveM!.Length == 3, nameof(this.CurveM), $"{nameof(this.CurveM)} must have a length of three"); this.InputChannelCount = this.OutputChannelCount = 3; } else if (this.IsAClutB()) { - Guard.MustBeBetweenOrEqualTo(this.CurveA.Length, 1, 15, nameof(this.CurveA)); - Guard.MustBeBetweenOrEqualTo(this.CurveB.Length, 1, 15, nameof(this.CurveB)); + Guard.MustBeBetweenOrEqualTo(this.CurveA!.Length, 1, 15, nameof(this.CurveA)); + Guard.MustBeBetweenOrEqualTo(this.CurveB!.Length, 1, 15, nameof(this.CurveB)); - this.InputChannelCount = curveA.Length; - this.OutputChannelCount = curveB.Length; + this.InputChannelCount = curveA!.Length; + this.OutputChannelCount = curveB!.Length; - Guard.IsTrue(this.InputChannelCount == clutValues.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); + Guard.IsTrue(this.InputChannelCount == clutValues!.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); Guard.IsTrue(this.OutputChannelCount == clutValues.OutputChannelCount, nameof(clutValues), "Output channel count does not match the CLUT size"); } else if (this.IsB()) { - this.InputChannelCount = this.OutputChannelCount = this.CurveB.Length; + this.InputChannelCount = this.OutputChannelCount = this.CurveB!.Length; } else { @@ -126,28 +126,28 @@ public IccLutAToBTagDataEntry( /// /// Gets the color lookup table /// - public IccClut ClutValues { get; } + public IccClut? ClutValues { get; } /// /// Gets the B Curve /// - public IccTagDataEntry[] CurveB { get; } + public IccTagDataEntry[]? CurveB { get; } /// /// Gets the M Curve /// - public IccTagDataEntry[] CurveM { get; } + public IccTagDataEntry[]? CurveM { get; } /// /// Gets the A Curve /// - public IccTagDataEntry[] CurveA { get; } + public IccTagDataEntry[]? CurveA { get; } /// - public override bool Equals(IccTagDataEntry other) => other is IccLutAToBTagDataEntry entry && this.Equals(entry); + public override bool Equals(IccTagDataEntry? other) => other is IccLutAToBTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccLutAToBTagDataEntry other) + public bool Equals(IccLutAToBTagDataEntry? other) { if (other is null) { @@ -164,14 +164,14 @@ public bool Equals(IccLutAToBTagDataEntry other) && this.OutputChannelCount == other.OutputChannelCount && this.Matrix3x3.Equals(other.Matrix3x3) && this.Matrix3x1.Equals(other.Matrix3x1) - && this.ClutValues.Equals(other.ClutValues) + && this.ClutValues!.Equals(other.ClutValues) && EqualsCurve(this.CurveB, other.CurveB) && EqualsCurve(this.CurveM, other.CurveM) && EqualsCurve(this.CurveA, other.CurveA); } /// - public override bool Equals(object obj) => obj is IccLutAToBTagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccLutAToBTagDataEntry other && this.Equals(other); /// public override int GetHashCode() @@ -191,7 +191,7 @@ public override int GetHashCode() return hashCode.ToHashCode(); } - private static bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] entryCurves) + private static bool EqualsCurve(IccTagDataEntry[]? thisCurves, IccTagDataEntry[]? entryCurves) { bool thisNull = thisCurves is null; bool entryNull = entryCurves is null; @@ -206,7 +206,7 @@ private static bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] return false; } - return thisCurves.SequenceEqual(entryCurves); + return thisCurves!.SequenceEqual(entryCurves!); } private bool IsAClutMMatrixB() @@ -230,7 +230,7 @@ private bool IsAClutB() private bool IsB() => this.CurveB != null; - private void VerifyCurve(IccTagDataEntry[] curves, string name) + private void VerifyCurve(IccTagDataEntry[]? curves, string name) { if (curves != null) { @@ -239,7 +239,7 @@ private void VerifyCurve(IccTagDataEntry[] curves, string name) } } - private static void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) + private static void VerifyMatrix(float[,]? matrix3x3, float[]? matrix3x1) { if (matrix3x1 != null) { @@ -263,7 +263,7 @@ private static void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) return new Vector3(matrix[0], matrix[1], matrix[2]); } - private static Matrix4x4? CreateMatrix3x3(float[,] matrix) + private static Matrix4x4? CreateMatrix3x3(float[,]? matrix) { if (matrix is null) { diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs index 491d50df1a..d399ccf1bc 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs @@ -21,12 +21,12 @@ internal sealed class IccLutBToATagDataEntry : IccTagDataEntry, IEquatableCLUT /// A Curve public IccLutBToATagDataEntry( - IccTagDataEntry[] curveB, - float[,] matrix3x3, - float[] matrix3x1, - IccTagDataEntry[] curveM, - IccClut clutValues, - IccTagDataEntry[] curveA) + IccTagDataEntry[]? curveB, + float[,]? matrix3x3, + float[]? matrix3x1, + IccTagDataEntry[]? curveM, + IccClut? clutValues, + IccTagDataEntry[]? curveA) : this(curveB, matrix3x3, matrix3x1, curveM, clutValues, curveA, IccProfileTag.Unknown) { } @@ -42,12 +42,12 @@ public IccLutBToATagDataEntry( /// A Curve /// Tag Signature public IccLutBToATagDataEntry( - IccTagDataEntry[] curveB, - float[,] matrix3x3, - float[] matrix3x1, - IccTagDataEntry[] curveM, - IccClut clutValues, - IccTagDataEntry[] curveA, + IccTagDataEntry[]? curveB, + float[,]? matrix3x3, + float[]? matrix3x1, + IccTagDataEntry[]? curveM, + IccClut? clutValues, + IccTagDataEntry[]? curveA, IccProfileTag tagSignature) : base(IccTypeSignature.LutBToA, tagSignature) { @@ -65,37 +65,37 @@ public IccLutBToATagDataEntry( if (this.IsBMatrixMClutA()) { - Guard.IsTrue(this.CurveB.Length == 3, nameof(this.CurveB), $"{nameof(this.CurveB)} must have a length of three"); - Guard.IsTrue(this.CurveM.Length == 3, nameof(this.CurveM), $"{nameof(this.CurveM)} must have a length of three"); - Guard.MustBeBetweenOrEqualTo(this.CurveA.Length, 1, 15, nameof(this.CurveA)); + Guard.IsTrue(this.CurveB!.Length == 3, nameof(this.CurveB), $"{nameof(this.CurveB)} must have a length of three"); + Guard.IsTrue(this.CurveM!.Length! == 3, nameof(this.CurveM), $"{nameof(this.CurveM)} must have a length of three"); + Guard.MustBeBetweenOrEqualTo(this.CurveA!.Length, 1, 15, nameof(this.CurveA)); this.InputChannelCount = 3; - this.OutputChannelCount = curveA.Length; + this.OutputChannelCount = curveA!.Length; - Guard.IsTrue(this.InputChannelCount == clutValues.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); + Guard.IsTrue(this.InputChannelCount == clutValues!.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); Guard.IsTrue(this.OutputChannelCount == clutValues.OutputChannelCount, nameof(clutValues), "Output channel count does not match the CLUT size"); } else if (this.IsBMatrixM()) { - Guard.IsTrue(this.CurveB.Length == 3, nameof(this.CurveB), $"{nameof(this.CurveB)} must have a length of three"); - Guard.IsTrue(this.CurveM.Length == 3, nameof(this.CurveM), $"{nameof(this.CurveM)} must have a length of three"); + Guard.IsTrue(this.CurveB!.Length == 3, nameof(this.CurveB), $"{nameof(this.CurveB)} must have a length of three"); + Guard.IsTrue(this.CurveM!.Length == 3, nameof(this.CurveM), $"{nameof(this.CurveM)} must have a length of three"); this.InputChannelCount = this.OutputChannelCount = 3; } else if (this.IsBClutA()) { - Guard.MustBeBetweenOrEqualTo(this.CurveA.Length, 1, 15, nameof(this.CurveA)); - Guard.MustBeBetweenOrEqualTo(this.CurveB.Length, 1, 15, nameof(this.CurveB)); + Guard.MustBeBetweenOrEqualTo(this.CurveA!.Length, 1, 15, nameof(this.CurveA)); + Guard.MustBeBetweenOrEqualTo(this.CurveB!.Length, 1, 15, nameof(this.CurveB)); - this.InputChannelCount = curveB.Length; - this.OutputChannelCount = curveA.Length; + this.InputChannelCount = curveB!.Length; + this.OutputChannelCount = curveA!.Length; - Guard.IsTrue(this.InputChannelCount == clutValues.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); + Guard.IsTrue(this.InputChannelCount == clutValues!.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); Guard.IsTrue(this.OutputChannelCount == clutValues.OutputChannelCount, nameof(clutValues), "Output channel count does not match the CLUT size"); } else if (this.IsB()) { - this.InputChannelCount = this.OutputChannelCount = this.CurveB.Length; + this.InputChannelCount = this.OutputChannelCount = this.CurveB!.Length; } else { @@ -126,28 +126,28 @@ public IccLutBToATagDataEntry( /// /// Gets the color lookup table /// - public IccClut ClutValues { get; } + public IccClut? ClutValues { get; } /// /// Gets the B Curve /// - public IccTagDataEntry[] CurveB { get; } + public IccTagDataEntry[]? CurveB { get; } /// /// Gets the M Curve /// - public IccTagDataEntry[] CurveM { get; } + public IccTagDataEntry[]? CurveM { get; } /// /// Gets the A Curve /// - public IccTagDataEntry[] CurveA { get; } + public IccTagDataEntry[]? CurveA { get; } /// - public override bool Equals(IccTagDataEntry other) => other is IccLutBToATagDataEntry entry && this.Equals(entry); + public override bool Equals(IccTagDataEntry? other) => other is IccLutBToATagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccLutBToATagDataEntry other) + public bool Equals(IccLutBToATagDataEntry? other) { if (other is null) { @@ -164,14 +164,14 @@ public bool Equals(IccLutBToATagDataEntry other) && this.OutputChannelCount == other.OutputChannelCount && this.Matrix3x3.Equals(other.Matrix3x3) && this.Matrix3x1.Equals(other.Matrix3x1) - && this.ClutValues.Equals(other.ClutValues) + && this.ClutValues!.Equals(other.ClutValues) && EqualsCurve(this.CurveB, other.CurveB) && EqualsCurve(this.CurveM, other.CurveM) && EqualsCurve(this.CurveA, other.CurveA); } /// - public override bool Equals(object obj) => obj is IccLutBToATagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccLutBToATagDataEntry other && this.Equals(other); /// public override int GetHashCode() @@ -190,7 +190,7 @@ public override int GetHashCode() return hashCode.ToHashCode(); } - private static bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] entryCurves) + private static bool EqualsCurve(IccTagDataEntry[]? thisCurves, IccTagDataEntry[]? entryCurves) { bool thisNull = thisCurves is null; bool entryNull = entryCurves is null; @@ -205,7 +205,7 @@ private static bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] return false; } - return thisCurves.SequenceEqual(entryCurves); + return thisCurves!.SequenceEqual(entryCurves!); } private bool IsBMatrixMClutA() @@ -219,7 +219,7 @@ private bool IsBClutA() private bool IsB() => this.CurveB != null; - private void VerifyCurve(IccTagDataEntry[] curves, string name) + private void VerifyCurve(IccTagDataEntry[]? curves, string name) { if (curves != null) { @@ -228,7 +228,7 @@ private void VerifyCurve(IccTagDataEntry[] curves, string name) } } - private static void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) + private static void VerifyMatrix(float[,]? matrix3x3, float[]? matrix3x1) { if (matrix3x1 != null) { @@ -242,7 +242,7 @@ private static void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) } } - private static Vector3? CreateMatrix3x1(float[] matrix) + private static Vector3? CreateMatrix3x1(float[]? matrix) { if (matrix is null) { @@ -252,7 +252,7 @@ private static void VerifyMatrix(float[,] matrix3x3, float[] matrix3x1) return new Vector3(matrix[0], matrix[1], matrix[2]); } - private static Matrix4x4? CreateMatrix3x3(float[,] matrix) + private static Matrix4x4? CreateMatrix3x3(float[,]? matrix) { if (matrix is null) { diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs index fd27948d2f..5e20579a35 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs @@ -70,13 +70,13 @@ public IccMeasurementTagDataEntry(IccStandardObserver observer, Vector3 xyzBacki public IccStandardIlluminant Illuminant { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccMeasurementTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccMeasurementTagDataEntry other) + public bool Equals(IccMeasurementTagDataEntry? other) { if (other is null) { @@ -97,7 +97,7 @@ public bool Equals(IccMeasurementTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccMeasurementTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs index 95d338244d..eb2cfcf6c1 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs @@ -35,13 +35,13 @@ public IccMultiLocalizedUnicodeTagDataEntry(IccLocalizedString[] texts, IccProfi public IccLocalizedString[] Texts { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccMultiLocalizedUnicodeTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccMultiLocalizedUnicodeTagDataEntry other) + public bool Equals(IccMultiLocalizedUnicodeTagDataEntry? other) { if (other is null) { @@ -57,7 +57,7 @@ public bool Equals(IccMultiLocalizedUnicodeTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccMultiLocalizedUnicodeTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs index 3c785fce86..1739eb66eb 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs @@ -53,11 +53,11 @@ public IccMultiProcessElementsTagDataEntry(IccMultiProcessElement[] data, IccPro public IccMultiProcessElement[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccMultiProcessElementsTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccMultiProcessElementsTagDataEntry other) + public bool Equals(IccMultiProcessElementsTagDataEntry? other) { if (other is null) { @@ -76,7 +76,7 @@ public bool Equals(IccMultiProcessElementsTagDataEntry other) } /// - public override bool Equals(object obj) => obj is IccMultiProcessElementsTagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccMultiProcessElementsTagDataEntry other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs index 37cd25d7c1..bf4e49ee0e 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs @@ -71,7 +71,7 @@ public IccNamedColor2TagDataEntry(string prefix, string suffix, IccNamedColor[] /// Suffix /// The named colors /// Tag Signature - public IccNamedColor2TagDataEntry(int vendorFlags, string prefix, string suffix, IccNamedColor[] colors, IccProfileTag tagSignature) + public IccNamedColor2TagDataEntry(int vendorFlags, string? prefix, string? suffix, IccNamedColor[] colors, IccProfileTag tagSignature) : base(IccTypeSignature.NamedColor2, tagSignature) { Guard.NotNull(colors, nameof(colors)); @@ -99,12 +99,12 @@ public IccNamedColor2TagDataEntry(int vendorFlags, string prefix, string suffix, /// /// Gets the prefix /// - public string Prefix { get; } + public string? Prefix { get; } /// /// Gets the suffix /// - public string Suffix { get; } + public string? Suffix { get; } /// /// Gets the vendor specific flags @@ -117,11 +117,11 @@ public IccNamedColor2TagDataEntry(int vendorFlags, string prefix, string suffix, public IccNamedColor[] Colors { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccNamedColor2TagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccNamedColor2TagDataEntry other) + public bool Equals(IccNamedColor2TagDataEntry? other) { if (other is null) { @@ -142,7 +142,7 @@ public bool Equals(IccNamedColor2TagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccNamedColor2TagDataEntry other && this.Equals(other); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs index d048990ac5..3a03ba8559 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs @@ -35,13 +35,13 @@ public IccParametricCurveTagDataEntry(IccParametricCurve curve, IccProfileTag ta public IccParametricCurve Curve { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccParametricCurveTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccParametricCurveTagDataEntry other) + public bool Equals(IccParametricCurveTagDataEntry? other) { if (other is null) { @@ -57,7 +57,7 @@ public bool Equals(IccParametricCurveTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccParametricCurveTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs index 37cae5a00c..92754088bd 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs @@ -34,11 +34,11 @@ public IccProfileSequenceDescTagDataEntry(IccProfileDescription[] descriptions, public IccProfileDescription[] Descriptions { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccProfileSequenceDescTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccProfileSequenceDescTagDataEntry other) + public bool Equals(IccProfileSequenceDescTagDataEntry? other) { if (other is null) { @@ -54,7 +54,7 @@ public bool Equals(IccProfileSequenceDescTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccProfileSequenceDescTagDataEntry other && this.Equals(other); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs index 351db6a252..ea1062d118 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs @@ -35,13 +35,13 @@ public IccProfileSequenceIdentifierTagDataEntry(IccProfileSequenceIdentifier[] d public IccProfileSequenceIdentifier[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccProfileSequenceIdentifierTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccProfileSequenceIdentifierTagDataEntry other) + public bool Equals(IccProfileSequenceIdentifierTagDataEntry? other) { if (other is null) { @@ -57,7 +57,7 @@ public bool Equals(IccProfileSequenceIdentifierTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccProfileSequenceIdentifierTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs index 669f269582..1c1680ded7 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs @@ -48,10 +48,10 @@ public IccResponseCurveSet16TagDataEntry(IccResponseCurve[] curves, IccProfileTa public IccResponseCurve[] Curves { get; } /// - public override bool Equals(IccTagDataEntry other) => other is IccResponseCurveSet16TagDataEntry entry && this.Equals(entry); + public override bool Equals(IccTagDataEntry? other) => other is IccResponseCurveSet16TagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccResponseCurveSet16TagDataEntry other) + public bool Equals(IccResponseCurveSet16TagDataEntry? other) { if (other is null) { @@ -69,7 +69,7 @@ public bool Equals(IccResponseCurveSet16TagDataEntry other) } /// - public override bool Equals(object obj) => obj is IccResponseCurveSet16TagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccResponseCurveSet16TagDataEntry other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs index 0f96b27838..d014782455 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs @@ -43,13 +43,13 @@ public IccScreeningTagDataEntry(IccScreeningFlag flags, IccScreeningChannel[] ch public IccScreeningChannel[] Channels { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccScreeningTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccScreeningTagDataEntry other) + public bool Equals(IccScreeningTagDataEntry? other) { if (other is null) { @@ -67,7 +67,7 @@ public bool Equals(IccScreeningTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccScreeningTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs index bff0a17531..4d58a0978c 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs @@ -33,11 +33,11 @@ public IccSignatureTagDataEntry(string signatureData, IccProfileTag tagSignature public string SignatureData { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccSignatureTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccSignatureTagDataEntry other) + public bool Equals(IccSignatureTagDataEntry? other) { if (other is null) { @@ -54,7 +54,7 @@ public bool Equals(IccSignatureTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccSignatureTagDataEntry other && this.Equals(other); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs index b951d7b56c..6d21fe93b0 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs @@ -18,7 +18,7 @@ internal sealed class IccTextDescriptionTagDataEntry : IccTagDataEntry, IEquatab /// ScriptCode text /// Unicode Language-Code /// ScriptCode Code - public IccTextDescriptionTagDataEntry(string ascii, string unicode, string scriptCode, uint unicodeLanguageCode, ushort scriptCodeCode) + public IccTextDescriptionTagDataEntry(string? ascii, string? unicode, string? scriptCode, uint unicodeLanguageCode, ushort scriptCodeCode) : this(ascii, unicode, scriptCode, unicodeLanguageCode, scriptCodeCode, IccProfileTag.Unknown) { } @@ -32,7 +32,7 @@ public IccTextDescriptionTagDataEntry(string ascii, string unicode, string scrip /// Unicode Language-Code /// ScriptCode Code /// Tag Signature - public IccTextDescriptionTagDataEntry(string ascii, string unicode, string scriptCode, uint unicodeLanguageCode, ushort scriptCodeCode, IccProfileTag tagSignature) + public IccTextDescriptionTagDataEntry(string? ascii, string? unicode, string? scriptCode, uint unicodeLanguageCode, ushort scriptCodeCode, IccProfileTag tagSignature) : base(IccTypeSignature.TextDescription, tagSignature) { this.Ascii = ascii; @@ -45,17 +45,17 @@ public IccTextDescriptionTagDataEntry(string ascii, string unicode, string scrip /// /// Gets the ASCII text /// - public string Ascii { get; } + public string? Ascii { get; } /// /// Gets the Unicode text /// - public string Unicode { get; } + public string? Unicode { get; } /// /// Gets the ScriptCode text /// - public string ScriptCode { get; } + public string? ScriptCode { get; } /// /// Gets the Unicode Language-Code @@ -73,7 +73,7 @@ public IccTextDescriptionTagDataEntry(string ascii, string unicode, string scrip /// /// The entry to convert /// The converted entry - public static explicit operator IccMultiLocalizedUnicodeTagDataEntry(IccTextDescriptionTagDataEntry textEntry) + public static explicit operator IccMultiLocalizedUnicodeTagDataEntry?(IccTextDescriptionTagDataEntry? textEntry) { if (textEntry is null) { @@ -83,7 +83,7 @@ public static explicit operator IccMultiLocalizedUnicodeTagDataEntry(IccTextDesc IccLocalizedString localString; if (!string.IsNullOrEmpty(textEntry.Unicode)) { - CultureInfo culture = GetCulture(textEntry.UnicodeLanguageCode); + CultureInfo? culture = GetCulture(textEntry.UnicodeLanguageCode); localString = culture != null ? new IccLocalizedString(culture, textEntry.Unicode) : new IccLocalizedString(textEntry.Unicode); @@ -103,7 +103,7 @@ public static explicit operator IccMultiLocalizedUnicodeTagDataEntry(IccTextDesc return new IccMultiLocalizedUnicodeTagDataEntry(new[] { localString }, textEntry.TagSignature); - static CultureInfo GetCulture(uint value) + static CultureInfo? GetCulture(uint value) { if (value == 0) { @@ -130,11 +130,11 @@ static CultureInfo GetCulture(uint value) } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccTextDescriptionTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccTextDescriptionTagDataEntry other) + public bool Equals(IccTextDescriptionTagDataEntry? other) { if (other is null) { @@ -155,7 +155,7 @@ public bool Equals(IccTextDescriptionTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccTextDescriptionTagDataEntry other && this.Equals(other); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs index feb5e4f4d1..5fd32e3592 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs @@ -32,11 +32,11 @@ public IccTextTagDataEntry(string text, IccProfileTag tagSignature) public string Text { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccTextTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccTextTagDataEntry other) + public bool Equals(IccTextTagDataEntry? other) { if (other is null) { @@ -52,7 +52,7 @@ public bool Equals(IccTextTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccTextTagDataEntry other && this.Equals(other); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs index 6763fc20c9..8e63153e18 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs @@ -34,13 +34,13 @@ public IccUFix16ArrayTagDataEntry(float[] data, IccProfileTag tagSignature) public float[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccUFix16ArrayTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccUFix16ArrayTagDataEntry other) + public bool Equals(IccUFix16ArrayTagDataEntry? other) { if (other is null) { @@ -56,7 +56,7 @@ public bool Equals(IccUFix16ArrayTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccUFix16ArrayTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs index 55d23976d9..43d3be683e 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs @@ -34,13 +34,13 @@ public IccUInt16ArrayTagDataEntry(ushort[] data, IccProfileTag tagSignature) public ushort[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccUInt16ArrayTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccUInt16ArrayTagDataEntry other) + public bool Equals(IccUInt16ArrayTagDataEntry? other) { if (other is null) { @@ -56,7 +56,7 @@ public bool Equals(IccUInt16ArrayTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccUInt16ArrayTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs index ffc4589ec2..06ff8fd6c5 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs @@ -34,13 +34,13 @@ public IccUInt32ArrayTagDataEntry(uint[] data, IccProfileTag tagSignature) public uint[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccUInt32ArrayTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccUInt32ArrayTagDataEntry other) + public bool Equals(IccUInt32ArrayTagDataEntry? other) { if (other is null) { @@ -56,7 +56,7 @@ public bool Equals(IccUInt32ArrayTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccUInt32ArrayTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs index b5f94dfdf9..4381bceaab 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs @@ -31,10 +31,10 @@ public IccUInt64ArrayTagDataEntry(ulong[] data, IccProfileTag tagSignature) public ulong[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) => other is IccUInt64ArrayTagDataEntry entry && this.Equals(entry); + public override bool Equals(IccTagDataEntry? other) => other is IccUInt64ArrayTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccUInt64ArrayTagDataEntry other) + public bool Equals(IccUInt64ArrayTagDataEntry? other) { if (other is null) { @@ -50,7 +50,7 @@ public bool Equals(IccUInt64ArrayTagDataEntry other) } /// - public override bool Equals(object obj) => obj is IccUInt64ArrayTagDataEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccUInt64ArrayTagDataEntry other && this.Equals(other); /// public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs index 3e8a8c3edd..7a339ce824 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs @@ -34,13 +34,13 @@ public IccUInt8ArrayTagDataEntry(byte[] data, IccProfileTag tagSignature) public byte[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccUInt8ArrayTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccUInt8ArrayTagDataEntry other) + public bool Equals(IccUInt8ArrayTagDataEntry? other) { if (other is null) { @@ -56,7 +56,7 @@ public bool Equals(IccUInt8ArrayTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccUInt8ArrayTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs index bfa76391e8..dde42a8952 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs @@ -51,11 +51,11 @@ public IccUcrBgTagDataEntry(ushort[] ucrCurve, ushort[] bgCurve, string descript public string Description { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) => other is IccUcrBgTagDataEntry entry && this.Equals(entry); /// - public bool Equals(IccUcrBgTagDataEntry other) + public bool Equals(IccUcrBgTagDataEntry? other) { if (other is null) { @@ -74,7 +74,7 @@ public bool Equals(IccUcrBgTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccUcrBgTagDataEntry other && this.Equals(other); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs index d580002adf..fab61c7289 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs @@ -34,13 +34,13 @@ public IccUnknownTagDataEntry(byte[] data, IccProfileTag tagSignature) public byte[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccUnknownTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccUnknownTagDataEntry other) + public bool Equals(IccUnknownTagDataEntry? other) { if (other is null) { @@ -56,7 +56,7 @@ public bool Equals(IccUnknownTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccUnknownTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs index 685212ed1b..113ae2577f 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs @@ -52,13 +52,13 @@ public IccViewingConditionsTagDataEntry(Vector3 illuminantXyz, Vector3 surroundX public IccStandardIlluminant Illuminant { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { return other is IccViewingConditionsTagDataEntry entry && this.Equals(entry); } /// - public bool Equals(IccViewingConditionsTagDataEntry other) + public bool Equals(IccViewingConditionsTagDataEntry? other) { if (other is null) { @@ -77,7 +77,7 @@ public bool Equals(IccViewingConditionsTagDataEntry other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccViewingConditionsTagDataEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs index 0dcb12de9a..c150034b40 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs @@ -34,7 +34,7 @@ public IccXyzTagDataEntry(Vector3[] data, IccProfileTag tagSignature) public Vector3[] Data { get; } /// - public override bool Equals(IccTagDataEntry other) + public override bool Equals(IccTagDataEntry? other) { if (base.Equals(other) && other is IccXyzTagDataEntry entry) { @@ -45,11 +45,11 @@ public override bool Equals(IccTagDataEntry other) } /// - public bool Equals(IccXyzTagDataEntry other) - => this.Equals((IccTagDataEntry)other); + public bool Equals(IccXyzTagDataEntry? other) + => this.Equals((IccTagDataEntry?)other); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => this.Equals(obj as IccXyzTagDataEntry); public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccClut.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccClut.cs index 6afab48c7d..26a882810e 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccClut.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccClut.cs @@ -111,7 +111,7 @@ public IccClut(byte[][] values, byte[] gridPointCount) public byte[] GridPointCount { get; } /// - public bool Equals(IccClut other) + public bool Equals(IccClut? other) { if (other is null) { @@ -131,7 +131,7 @@ public bool Equals(IccClut other) } /// - public override bool Equals(object obj) => obj is IccClut other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccClut other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccColorantTableEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccColorantTableEntry.cs index 46365316f8..a47e19cb6b 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccColorantTableEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccColorantTableEntry.cs @@ -83,7 +83,7 @@ public IccColorantTableEntry(string name, ushort pcs1, ushort pcs2, ushort pcs3) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccColorantTableEntry other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLocalizedString.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLocalizedString.cs index e97cd6b136..09294a2c6a 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLocalizedString.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLocalizedString.cs @@ -50,7 +50,7 @@ public bool Equals(IccLocalizedString other) => /// public override string ToString() => $"{this.Culture.Name}: {this.Text}"; - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccLocalizedString iccLocalizedString && this.Equals(iccLocalizedString); public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLut.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLut.cs index 93675099d9..5f07e55890 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLut.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccLut.cs @@ -66,7 +66,7 @@ public bool Equals(IccLut other) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccLut iccLut && this.Equals(iccLut); /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccNamedColor.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccNamedColor.cs index e79a8cf516..6e4e089c54 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccNamedColor.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccNamedColor.cs @@ -65,7 +65,7 @@ public IccNamedColor(string name, ushort[] pcsCoordinates, ushort[] deviceCoordi public static bool operator !=(IccNamedColor left, IccNamedColor right) => !left.Equals(right); /// - public override bool Equals(object obj) => obj is IccNamedColor other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccNamedColor other && this.Equals(other); /// public bool Equals(IccNamedColor other) diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccPositionNumber.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccPositionNumber.cs index 6a89fbda7e..27b6f83ac1 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccPositionNumber.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccPositionNumber.cs @@ -60,7 +60,7 @@ public IccPositionNumber(uint offset, uint size) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccPositionNumber other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileDescription.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileDescription.cs index ad29e99723..f20b0fab55 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileDescription.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileDescription.cs @@ -73,7 +73,7 @@ public bool Equals(IccProfileDescription other) => && this.DeviceModelInfo.AsSpan().SequenceEqual(other.DeviceModelInfo); /// - public override bool Equals(object obj) => obj is IccProfileDescription other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccProfileDescription other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileId.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileId.cs index 8b1c43d06d..ce38d527d0 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileId.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileId.cs @@ -80,7 +80,7 @@ public IccProfileId(uint p1, uint p2, uint p3, uint p4) public static bool operator !=(IccProfileId left, IccProfileId right) => !left.Equals(right); /// - public override bool Equals(object obj) => obj is IccProfileId other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccProfileId other && this.Equals(other); /// public bool Equals(IccProfileId other) => diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs index 093286fe92..93db530ebc 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs @@ -35,7 +35,7 @@ public bool Equals(IccProfileSequenceIdentifier other) => && this.Description.AsSpan().SequenceEqual(other.Description); /// - public override bool Equals(object obj) => obj is IccProfileSequenceIdentifier other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccProfileSequenceIdentifier other && this.Equals(other); /// public override int GetHashCode() => HashCode.Combine(this.Id, this.Description); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccResponseNumber.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccResponseNumber.cs index 5e2d57ec33..3d3f8862e9 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccResponseNumber.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccResponseNumber.cs @@ -60,7 +60,7 @@ public IccResponseNumber(ushort deviceCode, float measurementValue) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccResponseNumber other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccScreeningChannel.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccScreeningChannel.cs index 0666da235e..f6c39c28a9 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccScreeningChannel.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccScreeningChannel.cs @@ -76,7 +76,7 @@ public bool Equals(IccScreeningChannel other) => this.SpotShape == other.SpotShape; /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is IccScreeningChannel other && this.Equals(other); } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs index 539fe723e2..e7d7461d5d 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccTagTableEntry.cs @@ -67,7 +67,7 @@ public IccTagTableEntry(IccProfileTag signature, uint offset, uint dataSize) } /// - public override bool Equals(object obj) => obj is IccTagTableEntry other && this.Equals(other); + public override bool Equals(object? obj) => obj is IccTagTableEntry other && this.Equals(other); /// public bool Equals(IccTagTableEntry other) => diff --git a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccVersion.cs b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccVersion.cs index c280c8f372..63e8abeb5b 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/Various/IccVersion.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/Various/IccVersion.cs @@ -55,7 +55,7 @@ public IccVersion(int major, int minor, int patch) => !(left == right); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is IccVersion iccVersion && this.Equals(iccVersion); /// diff --git a/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs b/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs index 57039c42fa..d03298b1fd 100644 --- a/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs @@ -3,6 +3,7 @@ using System.Buffers.Binary; using System.Collections.ObjectModel; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Text; using SixLabors.ImageSharp.Metadata.Profiles.IPTC; @@ -14,7 +15,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc; /// public sealed class IptcProfile : IDeepCloneable { - private Collection values; + private Collection? values; private const byte IptcTagMarkerByte = 0x1c; @@ -29,7 +30,7 @@ public sealed class IptcProfile : IDeepCloneable /// Initializes a new instance of the class. /// public IptcProfile() - : this((byte[])null) + : this((byte[]?)null) { } @@ -37,7 +38,7 @@ public IptcProfile() /// Initializes a new instance of the class. /// /// The byte array to read the iptc profile from. - public IptcProfile(byte[] data) + public IptcProfile(byte[]? data) { this.Data = data; this.Initialize(); @@ -77,7 +78,7 @@ private IptcProfile(IptcProfile other) /// /// Gets the byte data of the IPTC profile. /// - public byte[] Data { get; private set; } + public byte[]? Data { get; private set; } /// /// Gets the values of this iptc profile. @@ -201,7 +202,7 @@ public void SetValue(IptcTag tag, Encoding encoding, string value, bool strict = } } - this.values.Add(new IptcValue(tag, encoding, value, strict)); + this.values?.Add(new IptcValue(tag, encoding, value, strict)); } /// @@ -309,6 +310,7 @@ private int WriteRecord(int offset, ReadOnlySpan recordData, IptcRecordNum return offset; } + [MemberNotNull(nameof(values))] private void Initialize() { if (this.values != null) @@ -358,7 +360,7 @@ private void Initialize() /// true if any value has UTF-8 encoding. private bool HasValuesInUtf8() { - foreach (IptcValue value in this.values) + foreach (IptcValue value in this.values!) { if (value.Encoding == Encoding.UTF8) { diff --git a/src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs b/src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs index af0c319b81..2070a4c21c 100644 --- a/src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs +++ b/src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc; /// public sealed class IptcValue : IDeepCloneable { - private byte[] data = Array.Empty(); + private byte[]? data = Array.Empty(); private Encoding encoding; internal IptcValue(IptcValue other) @@ -28,6 +28,7 @@ internal IptcValue(IptcValue other) this.Tag = other.Tag; this.Strict = other.Strict; + this.encoding = Encoding.UTF8; } internal IptcValue(IptcTag tag, byte[] value, bool strict) @@ -87,7 +88,7 @@ public Encoding Encoding /// public string Value { - get => this.encoding.GetString(this.data); + get => this.encoding.GetString(this.data!); set { if (string.IsNullOrEmpty(value)) @@ -122,7 +123,7 @@ public string Value /// /// Gets the length of the value. /// - public int Length => this.data.Length; + public int Length => this.data!.Length; /// public IptcValue DeepClone() => new IptcValue(this); @@ -132,14 +133,14 @@ public string Value /// /// The object to compare this with. /// True when the specified object is equal to the current . - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (ReferenceEquals(this, obj)) { return true; } - return this.Equals(obj as IptcValue); + return this.Equals((obj as IptcValue)!); } /// @@ -164,7 +165,7 @@ public bool Equals(IptcValue other) return false; } - if (this.data.Length != other.data.Length) + if (this.data!.Length != other.data!.Length) { return false; } @@ -192,7 +193,7 @@ public bool Equals(IptcValue other) /// A array. public byte[] ToByteArray() { - var result = new byte[this.data.Length]; + var result = new byte[this.data!.Length]; this.data.CopyTo(result, 0); return result; } @@ -208,10 +209,10 @@ public byte[] ToByteArray() /// /// The encoding to use. /// A string that represents the current value with the specified encoding. - public string ToString(Encoding encoding) + public string ToString(Encoding? encoding) { Guard.NotNull(encoding, nameof(encoding)); - return encoding.GetString(this.data); + return encoding.GetString(this.data!); } } diff --git a/src/ImageSharp/Metadata/Profiles/XMP/XmpProfile.cs b/src/ImageSharp/Metadata/Profiles/XMP/XmpProfile.cs index 0b22017aec..9ce5b944e3 100644 --- a/src/ImageSharp/Metadata/Profiles/XMP/XmpProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/XMP/XmpProfile.cs @@ -16,7 +16,7 @@ public sealed class XmpProfile : IDeepCloneable /// Initializes a new instance of the class. /// public XmpProfile() - : this((byte[])null) + : this((byte[]?)null) { } @@ -24,7 +24,7 @@ public XmpProfile() /// Initializes a new instance of the class. /// /// The UTF8 encoded byte array to read the XMP profile from. - public XmpProfile(byte[] data) => this.Data = data; + public XmpProfile(byte[]? data) => this.Data = data; /// /// Initializes a new instance of the class @@ -41,15 +41,15 @@ private XmpProfile(XmpProfile other) /// /// Gets the XMP raw data byte array. /// - internal byte[] Data { get; private set; } + internal byte[]? Data { get; private set; } /// /// Gets the raw XML document containing the XMP profile. /// /// The - public XDocument GetDocument() + public XDocument? GetDocument() { - byte[] byteArray = this.Data; + byte[]? byteArray = this.Data; if (byteArray is null) { return null; @@ -76,7 +76,7 @@ public XDocument GetDocument() /// The public byte[] ToByteArray() { - byte[] result = new byte[this.Data.Length]; + byte[] result = new byte[this.Data!.Length]; this.Data.AsSpan().CopyTo(result); return result; } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs index db4c5921c8..0256907121 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs @@ -139,7 +139,7 @@ public void ToRgba32(ref Rgba32 dest) /// /// The object to compare. /// True if the object is equal to the packed vector. - public override readonly bool Equals(object obj) => obj is A8 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is A8 other && this.Equals(other); /// /// Compares another A8 packed vector with the packed vector. diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Abgr32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Abgr32.cs index c1c10f09a5..ca68c5aaf9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Abgr32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Abgr32.cs @@ -334,7 +334,7 @@ public void FromRgba64(Rgba64 source) } /// - public override readonly bool Equals(object obj) => obj is Abgr32 abgr32 && this.Equals(abgr32); + public override readonly bool Equals(object? obj) => obj is Abgr32 abgr32 && this.Equals(abgr32); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs index a5e2b63c8b..0c99adb52d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs @@ -333,7 +333,7 @@ public void FromRgba64(Rgba64 source) } /// - public override readonly bool Equals(object obj) => obj is Argb32 argb32 && this.Equals(argb32); + public override readonly bool Equals(object? obj) => obj is Argb32 argb32 && this.Equals(argb32); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs index dbf02a77b9..65b36059b8 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs @@ -231,7 +231,7 @@ public void FromRgba64(Rgba64 source) public readonly bool Equals(Bgr24 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B); /// - public override readonly bool Equals(object obj) => obj is Bgr24 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Bgr24 other && this.Equals(other); /// public override readonly string ToString() => $"Bgr24({this.B}, {this.G}, {this.R})"; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs index 853ebaa63b..ac3b6f8299 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs @@ -150,7 +150,7 @@ public void FromVector4(Vector4 vector) (this.PackedValue & 0x1F) * (1F / 31F)); /// - public override readonly bool Equals(object obj) => obj is Bgr565 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Bgr565 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs index 46e6a41384..6b859cda64 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs @@ -286,7 +286,7 @@ public void FromRgba64(Rgba64 source) } /// - public override readonly bool Equals(object obj) => obj is Bgra32 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Bgra32 other && this.Equals(other); /// public readonly bool Equals(Bgra32 other) => this.Bgra.Equals(other.Bgra); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs index 2e3e53eecc..8ba32c8ac2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs @@ -142,7 +142,7 @@ public readonly Vector4 ToVector4() public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); /// - public override readonly bool Equals(object obj) => obj is Bgra4444 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Bgra4444 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs index 03660df7ae..c282f03d89 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs @@ -140,7 +140,7 @@ public Bgra5551(float x, float y, float z, float w) public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); /// - public override bool Equals(object obj) => obj is Bgra5551 other && this.Equals(other); + public override bool Equals(object? obj) => obj is Bgra5551 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs index 1797483b4c..e699e5fe58 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs @@ -140,7 +140,7 @@ public Byte4(float x, float y, float z, float w) public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); /// - public override readonly bool Equals(object obj) => obj is Byte4 byte4 && this.Equals(byte4); + public override readonly bool Equals(object? obj) => obj is Byte4 byte4 && this.Equals(byte4); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs index 56f6e35280..db1e02adc2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs @@ -139,7 +139,7 @@ public readonly Vector4 ToScaledVector4() public readonly float ToSingle() => HalfTypeHelper.Unpack(this.PackedValue); /// - public override readonly bool Equals(object obj) => obj is HalfSingle other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is HalfSingle other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs index 57864f990b..9caae58c95 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs @@ -156,7 +156,7 @@ public readonly Vector2 ToVector2() } /// - public override readonly bool Equals(object obj) => obj is HalfVector2 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is HalfVector2 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs index bd25991194..609fec3bd7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs @@ -148,7 +148,7 @@ public readonly Vector4 ToScaledVector4() public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); /// - public override readonly bool Equals(object obj) => obj is HalfVector4 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is HalfVector4 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs b/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs index f826863331..c6ee8744d9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs @@ -152,7 +152,7 @@ public void ToRgba32(ref Rgba32 dest) public void FromRgba64(Rgba64 source) => this.PackedValue = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B); /// - public override readonly bool Equals(object obj) => obj is L16 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is L16 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs index d08eee0170..383e09b270 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs @@ -142,7 +142,7 @@ public void FromRgba64(Rgba64 source) ColorNumerics.DownScaleFrom16BitTo8Bit(source.B)); /// - public override readonly bool Equals(object obj) => obj is L8 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is L8 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs b/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs index e44ca56344..7597677a26 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs @@ -79,7 +79,7 @@ public ushort PackedValue public readonly bool Equals(La16 other) => this.PackedValue.Equals(other.PackedValue); /// - public override readonly bool Equals(object obj) => obj is La16 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is La16 other && this.Equals(other); /// public override readonly string ToString() => $"La16({this.L}, {this.A})"; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs index 46dce621b2..cb8fad228d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs @@ -81,7 +81,7 @@ public uint PackedValue public readonly bool Equals(La32 other) => this.PackedValue.Equals(other.PackedValue); /// - public override readonly bool Equals(object obj) => obj is La32 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is La32 other && this.Equals(other); /// public override readonly string ToString() => $"La32({this.L}, {this.A})"; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs index f5ce19340d..92b9e6148a 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs @@ -161,7 +161,7 @@ public void FromVector4(Vector4 vector) (sbyte)((this.PackedValue >> 8) & 0xFF) / MaxPos); /// - public override readonly bool Equals(object obj) => obj is NormalizedByte2 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is NormalizedByte2 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs index fe4054c8b6..f87bb5a602 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs @@ -153,7 +153,7 @@ public readonly Vector4 ToScaledVector4() public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); /// - public override readonly bool Equals(object obj) => obj is NormalizedByte4 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is NormalizedByte4 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs index 8502013e2d..f77dd69b71 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs @@ -162,7 +162,7 @@ public void FromVector4(Vector4 vector) (short)(this.PackedValue >> 0x10) / MaxPos); /// - public override readonly bool Equals(object obj) => obj is NormalizedShort2 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is NormalizedShort2 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs index dcc6046e70..989edbd2ba 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs @@ -154,7 +154,7 @@ public readonly Vector4 ToScaledVector4() public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); /// - public override readonly bool Equals(object obj) => obj is NormalizedShort4 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is NormalizedShort4 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs index 765349fc00..0a13a15eda 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs @@ -145,7 +145,7 @@ public void FromVector4(Vector4 vector) public readonly Vector2 ToVector2() => new Vector2(this.PackedValue & 0xFFFF, (this.PackedValue >> 16) & 0xFFFF) / Max; /// - public override readonly bool Equals(object obj) => obj is Rg32 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Rg32 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs index e090b6ba2d..105618cd96 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs @@ -240,7 +240,7 @@ public void FromRgba64(Rgba64 source) } /// - public override readonly bool Equals(object obj) => obj is Rgb24 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Rgb24 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs index 40ece1932e..1cf63eb24c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs @@ -209,7 +209,7 @@ public void ToRgba32(ref Rgba32 dest) public void FromRgb48(Rgb48 source) => this = source; /// - public override readonly bool Equals(object obj) => obj is Rgb48 rgb48 && this.Equals(rgb48); + public override readonly bool Equals(object? obj) => obj is Rgb48 rgb48 && this.Equals(rgb48); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs index a96cded500..7bac1d9208 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs @@ -140,7 +140,7 @@ public Rgba1010102(float x, float y, float z, float w) public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); /// - public override readonly bool Equals(object obj) => obj is Rgba1010102 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Rgba1010102 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs index ea35cccbf7..a652c2b339 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -266,7 +266,7 @@ public static Rgba32 ParseHex(string hex) /// The . /// [MethodImpl(InliningOptions.ShortMethod)] - public static bool TryParseHex(string hex, out Rgba32 result) + public static bool TryParseHex(string? hex, out Rgba32 result) { result = default; if (string.IsNullOrWhiteSpace(hex)) @@ -436,7 +436,7 @@ public readonly string ToHex() } /// - public override readonly bool Equals(object obj) => obj is Rgba32 rgba32 && this.Equals(rgba32); + public override readonly bool Equals(object? obj) => obj is Rgba32 rgba32 && this.Equals(rgba32); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -513,7 +513,7 @@ private void Pack(ref Vector4 vector) /// /// A rrggbbaa hex value. /// - private static string ToRgbaHex(string hex) + private static string? ToRgbaHex(string hex) { if (hex[0] == '#') { diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs index 21591f7d1a..81c9591480 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs @@ -443,7 +443,7 @@ public readonly Bgr24 ToBgr24() } /// - public override readonly bool Equals(object obj) => obj is Rgba64 rgba64 && this.Equals(rgba64); + public override readonly bool Equals(object? obj) => obj is Rgba64 rgba64 && this.Equals(rgba64); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs index 96b87bcf4a..899987b712 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs @@ -192,7 +192,7 @@ public readonly string ToHex() } /// - public override readonly bool Equals(object obj) => obj is RgbaVector other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is RgbaVector other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs index 6f657e17c0..832e8c770f 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs @@ -163,7 +163,7 @@ public void FromVector4(Vector4 vector) public readonly Vector2 ToVector2() => new((short)(this.PackedValue & 0xFFFF), (short)(this.PackedValue >> 0x10)); /// - public override readonly bool Equals(object obj) => obj is Short2 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Short2 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs index 1fbc145fea..c4dc324a13 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs @@ -163,7 +163,7 @@ public void ToRgba32(ref Rgba32 dest) public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); /// - public override readonly bool Equals(object obj) => obj is Short4 other && this.Equals(other); + public override readonly bool Equals(object? obj) => obj is Short4 other && this.Equals(other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/Primitives/ColorMatrix.cs b/src/ImageSharp/Primitives/ColorMatrix.cs index ce3acb2b3f..e06dc1f6a5 100644 --- a/src/ImageSharp/Primitives/ColorMatrix.cs +++ b/src/ImageSharp/Primitives/ColorMatrix.cs @@ -390,7 +390,7 @@ public bool IsIdentity public static bool operator !=(ColorMatrix value1, ColorMatrix value2) => !value1.Equals(value2); /// - public override bool Equals(object obj) => obj is ColorMatrix matrix && this.Equals(matrix); + public override bool Equals(object? obj) => obj is ColorMatrix matrix && this.Equals(matrix); /// public bool Equals(ColorMatrix other) => diff --git a/src/ImageSharp/Primitives/Complex64.cs b/src/ImageSharp/Primitives/Complex64.cs index b5544bcf56..4baedd9bae 100644 --- a/src/ImageSharp/Primitives/Complex64.cs +++ b/src/ImageSharp/Primitives/Complex64.cs @@ -77,7 +77,7 @@ public bool Equals(Complex64 other) } /// - public override bool Equals(object obj) => obj is Complex64 other && this.Equals(other); + public override bool Equals(object? obj) => obj is Complex64 other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Primitives/ComplexVector4.cs b/src/ImageSharp/Primitives/ComplexVector4.cs index 0feffdb36f..39bd2c2bab 100644 --- a/src/ImageSharp/Primitives/ComplexVector4.cs +++ b/src/ImageSharp/Primitives/ComplexVector4.cs @@ -48,7 +48,7 @@ public bool Equals(ComplexVector4 other) } /// - public override bool Equals(object obj) => obj is ComplexVector4 other && this.Equals(other); + public override bool Equals(object? obj) => obj is ComplexVector4 other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Primitives/DenseMatrix{T}.cs b/src/ImageSharp/Primitives/DenseMatrix{T}.cs index 4b00323640..9849e0211f 100644 --- a/src/ImageSharp/Primitives/DenseMatrix{T}.cs +++ b/src/ImageSharp/Primitives/DenseMatrix{T}.cs @@ -248,7 +248,7 @@ private void CheckCoordinates(int row, int column) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is DenseMatrix other && this.Equals(other); /// diff --git a/src/ImageSharp/Primitives/LongRational.cs b/src/ImageSharp/Primitives/LongRational.cs index baf01364d9..e92875a98b 100644 --- a/src/ImageSharp/Primitives/LongRational.cs +++ b/src/ImageSharp/Primitives/LongRational.cs @@ -66,7 +66,7 @@ public LongRational(long numerator, long denominator) public bool IsZero => this.Denominator == 1 && this.Numerator == 0; /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is LongRational longRational && this.Equals(longRational); /// diff --git a/src/ImageSharp/Primitives/Number.cs b/src/ImageSharp/Primitives/Number.cs index 62ac1e4de7..fae67bbea1 100644 --- a/src/ImageSharp/Primitives/Number.cs +++ b/src/ImageSharp/Primitives/Number.cs @@ -145,7 +145,7 @@ public int CompareTo(Number other) } /// - public override bool Equals(object obj) => obj is Number other && this.Equals(other); + public override bool Equals(object? obj) => obj is Number other && this.Equals(other); /// public bool Equals(Number other) diff --git a/src/ImageSharp/Primitives/Point.cs b/src/ImageSharp/Primitives/Point.cs index c7f13f771d..8ace7ffacf 100644 --- a/src/ImageSharp/Primitives/Point.cs +++ b/src/ImageSharp/Primitives/Point.cs @@ -274,7 +274,7 @@ public void Offset(int dx, int dy) public override string ToString() => $"Point [ X={this.X}, Y={this.Y} ]"; /// - public override bool Equals(object obj) => obj is Point other && this.Equals(other); + public override bool Equals(object? obj) => obj is Point other && this.Equals(other); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Primitives/PointF.cs b/src/ImageSharp/Primitives/PointF.cs index a07a11582d..de363e2bd3 100644 --- a/src/ImageSharp/Primitives/PointF.cs +++ b/src/ImageSharp/Primitives/PointF.cs @@ -283,7 +283,7 @@ public void Offset(float dx, float dy) public override string ToString() => $"PointF [ X={this.X}, Y={this.Y} ]"; /// - public override bool Equals(object obj) => obj is PointF pointF && this.Equals(pointF); + public override bool Equals(object? obj) => obj is PointF pointF && this.Equals(pointF); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Primitives/Rational.cs b/src/ImageSharp/Primitives/Rational.cs index 515af45960..59f34331a7 100644 --- a/src/ImageSharp/Primitives/Rational.cs +++ b/src/ImageSharp/Primitives/Rational.cs @@ -122,7 +122,7 @@ public Rational(double value, bool bestPrecision) public static Rational FromDouble(double value, bool bestPrecision) => new Rational(value, bestPrecision); /// - public override bool Equals(object obj) => obj is Rational other && this.Equals(other); + public override bool Equals(object? obj) => obj is Rational other && this.Equals(other); /// public bool Equals(Rational other) diff --git a/src/ImageSharp/Primitives/Rectangle.cs b/src/ImageSharp/Primitives/Rectangle.cs index 7f32acae79..baffbc7f49 100644 --- a/src/ImageSharp/Primitives/Rectangle.cs +++ b/src/ImageSharp/Primitives/Rectangle.cs @@ -443,7 +443,7 @@ public void Offset(int dx, int dy) public override string ToString() => $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; /// - public override bool Equals(object obj) => obj is Rectangle other && this.Equals(other); + public override bool Equals(object? obj) => obj is Rectangle other && this.Equals(other); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Primitives/RectangleF.cs b/src/ImageSharp/Primitives/RectangleF.cs index a8a584ba5f..68add77d09 100644 --- a/src/ImageSharp/Primitives/RectangleF.cs +++ b/src/ImageSharp/Primitives/RectangleF.cs @@ -378,7 +378,7 @@ public override string ToString() => $"RectangleF [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; /// - public override bool Equals(object obj) => obj is RectangleF other && this.Equals(other); + public override bool Equals(object? obj) => obj is RectangleF other && this.Equals(other); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Primitives/SignedRational.cs b/src/ImageSharp/Primitives/SignedRational.cs index 25dc70441f..d56ea825e6 100644 --- a/src/ImageSharp/Primitives/SignedRational.cs +++ b/src/ImageSharp/Primitives/SignedRational.cs @@ -134,7 +134,7 @@ public static SignedRational FromDouble(double value, bool bestPrecision) } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is SignedRational other && this.Equals(other); } diff --git a/src/ImageSharp/Primitives/Size.cs b/src/ImageSharp/Primitives/Size.cs index 8287653fdc..945b680daa 100644 --- a/src/ImageSharp/Primitives/Size.cs +++ b/src/ImageSharp/Primitives/Size.cs @@ -268,7 +268,7 @@ public void Deconstruct(out int width, out int height) public override string ToString() => $"Size [ Width={this.Width}, Height={this.Height} ]"; /// - public override bool Equals(object obj) => obj is Size other && this.Equals(other); + public override bool Equals(object? obj) => obj is Size other && this.Equals(other); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Primitives/SizeF.cs b/src/ImageSharp/Primitives/SizeF.cs index 818ddf180a..36cf9eb8ef 100644 --- a/src/ImageSharp/Primitives/SizeF.cs +++ b/src/ImageSharp/Primitives/SizeF.cs @@ -214,7 +214,7 @@ public void Deconstruct(out float width, out float height) public override string ToString() => $"SizeF [ Width={this.Width}, Height={this.Height} ]"; /// - public override bool Equals(object obj) => obj is SizeF && this.Equals((SizeF)obj); + public override bool Equals(object? obj) => obj is SizeF && this.Equals((SizeF)obj); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Primitives/ValueSize.cs b/src/ImageSharp/Primitives/ValueSize.cs index e3034d8a6f..f572dd658f 100644 --- a/src/ImageSharp/Primitives/ValueSize.cs +++ b/src/ImageSharp/Primitives/ValueSize.cs @@ -114,7 +114,7 @@ public float Calculate(Size size) public override string ToString() => $"{this.Value} - {this.Type}"; /// - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is ValueSize size && this.Equals(size); } diff --git a/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs b/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs index 35a2734577..41f3a99c25 100644 --- a/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs +++ b/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs @@ -16,7 +16,7 @@ internal class DefaultImageProcessorContext : IInternalImageProcessingCo { private readonly bool mutate; private readonly Image source; - private Image destination; + private Image? destination; /// /// Initializes a new instance of the class. @@ -53,7 +53,7 @@ public Image GetResultImage() this.destination = this.source.Clone(); } - return this.destination; + return this.destination!; } /// @@ -86,7 +86,7 @@ public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectang } // Standard processing pipeline. - using (IImageProcessor specificProcessor = processor.CreatePixelSpecificProcessor(this.Configuration, this.destination, rectangle)) + using (IImageProcessor specificProcessor = processor.CreatePixelSpecificProcessor(this.Configuration, this.destination!, rectangle)) { specificProcessor.Execute(); } diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs index fdf0967c53..300e31b450 100644 --- a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs +++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs @@ -63,7 +63,7 @@ public static Buffer2D CalculateIntegralImage(this ImageFrame intImage = configuration.MemoryAllocator.Allocate2D(interest.Width, interest.Height); ulong sumX0 = 0; - Buffer2D sourceBuffer = source.PixelBuffer; + Buffer2D sourceBuffer = source.PixelBuffer!; using (IMemoryOwner tempRow = configuration.MemoryAllocator.Allocate(interest.Width)) { diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs index 575a6c1e4b..a08a9ed5ad 100644 --- a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs @@ -158,7 +158,7 @@ public static Image Clone(this Image source, Configuration configuration, Action var visitor = new ProcessingVisitor(configuration, operation, false); source.AcceptVisitor(visitor); - return visitor.ResultImage; + return visitor.ResultImage!; } /// @@ -281,7 +281,7 @@ public ProcessingVisitor(Configuration configuration, Action(Image image) where TPixel : unmanaged, IPixel diff --git a/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs index e3b2025aa5..2785dec6e9 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs @@ -42,7 +42,7 @@ protected override void OnFrameApply(ImageFrame source) byte clusterSize = (byte)Math.Clamp(interest.Width / 16F, 0, 255); using Buffer2D intImage = source.CalculateIntegralImage(interest); - RowOperation operation = new(configuration, interest, source.PixelBuffer, intImage, upper, lower, thresholdLimit, clusterSize); + RowOperation operation = new(configuration, interest, source.PixelBuffer!, intImage, upper, lower, thresholdLimit, clusterSize); ParallelRowIterator.IterateRows( configuration, interest, diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs index 1a35973fbd..ae7a98a2c2 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs @@ -41,7 +41,7 @@ protected override void OnFrameApply(ImageFrame source) var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); var operation = new RowOperation( interest.X, - source.PixelBuffer, + source.PixelBuffer!, upper, lower, threshold, diff --git a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs index bafe33c484..aa000a10e7 100644 --- a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs @@ -72,7 +72,7 @@ void IImageProcessor.Execute() // Create an interim clone of the source image to operate on. // Doing this allows for the application of transforms that will alter // the dimensions of the image. - Image clone = default; + Image? clone = default; try { clone = ((ICloningImageProcessor)this).CloneAndExecute(); diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index 7e7cf81385..fc10a7ef76 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -80,7 +80,7 @@ protected override void OnFrameApply(ImageFrame source) // Preliminary gamma highlight pass if (this.gamma == 3F) { - var gammaOperation = new ApplyGamma3ExposureRowOperation(sourceRectangle, source.PixelBuffer, this.Configuration); + var gammaOperation = new ApplyGamma3ExposureRowOperation(sourceRectangle, source.PixelBuffer!, this.Configuration); ParallelRowIterator.IterateRows( this.Configuration, sourceRectangle, @@ -88,7 +88,7 @@ protected override void OnFrameApply(ImageFrame source) } else { - var gammaOperation = new ApplyGammaExposureRowOperation(sourceRectangle, source.PixelBuffer, this.Configuration, this.gamma); + var gammaOperation = new ApplyGammaExposureRowOperation(sourceRectangle, source.PixelBuffer!, this.Configuration, this.gamma); ParallelRowIterator.IterateRows( this.Configuration, sourceRectangle, @@ -104,7 +104,7 @@ protected override void OnFrameApply(ImageFrame source) // Apply the inverse gamma exposure pass, and write the final pixel data if (this.gamma == 3F) { - var operation = new ApplyInverseGamma3ExposureRowOperation(sourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration); + var operation = new ApplyInverseGamma3ExposureRowOperation(sourceRectangle, source.PixelBuffer!, processingBuffer, this.Configuration); ParallelRowIterator.IterateRows( this.Configuration, sourceRectangle, @@ -112,7 +112,7 @@ protected override void OnFrameApply(ImageFrame source) } else { - var operation = new ApplyInverseGammaExposureRowOperation(sourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, 1 / this.gamma); + var operation = new ApplyInverseGammaExposureRowOperation(sourceRectangle, source.PixelBuffer!, processingBuffer, this.Configuration, 1 / this.gamma); ParallelRowIterator.IterateRows( this.Configuration, sourceRectangle, @@ -164,7 +164,7 @@ private void OnFrameApplyCore( var horizontalOperation = new FirstPassConvolutionRowOperation( sourceRectangle, firstPassBuffer, - source.PixelBuffer, + source.PixelBuffer!, mapXY, kernel, configuration); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs index b8a61e5a32..7af43d757c 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs @@ -76,7 +76,7 @@ protected override void OnFrameApply(ImageFrame source) var operation = new Convolution2DRowOperation( interest, targetPixels, - source.PixelBuffer, + source.PixelBuffer!, map, this.KernelY, this.KernelX, @@ -89,6 +89,6 @@ protected override void OnFrameApply(ImageFrame source) in operation); } - Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); + Buffer2D.SwapOrCopyContent(source.PixelBuffer!, targetPixels); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs index 7aa83b0dd0..a4bd0a1701 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs @@ -84,7 +84,7 @@ protected override void OnFrameApply(ImageFrame source) var horizontalOperation = new HorizontalConvolutionRowOperation( interest, firstPassPixels, - source.PixelBuffer, + source.PixelBuffer!, mapXY, this.Kernel, this.Configuration, @@ -98,7 +98,7 @@ protected override void OnFrameApply(ImageFrame source) // Vertical convolution var verticalOperation = new VerticalConvolutionRowOperation( interest, - source.PixelBuffer, + source.PixelBuffer!, firstPassPixels, mapXY, this.Kernel, diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs index d7a8f743c7..7c15115e15 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs @@ -64,14 +64,14 @@ protected override void OnFrameApply(ImageFrame source) { map.BuildSamplingOffsetMap(this.KernelXY, interest); - var operation = new RowOperation(interest, targetPixels, source.PixelBuffer, map, this.KernelXY, this.Configuration, this.PreserveAlpha); + var operation = new RowOperation(interest, targetPixels, source.PixelBuffer!, map, this.KernelXY, this.Configuration, this.PreserveAlpha); ParallelRowIterator.IterateRows( this.Configuration, operationBounds, in operation); } - Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); + Buffer2D.SwapOrCopyContent(source.PixelBuffer!, targetPixels); } /// diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs index 75e8e98e91..3617f32356 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs @@ -83,7 +83,7 @@ protected override void OnFrameApply(ImageFrame source) processor.Apply(pass); } - var operation = new RowOperation(source.PixelBuffer, pass.PixelBuffer, interest); + var operation = new RowOperation(source.PixelBuffer!, pass.PixelBuffer!, interest); ParallelRowIterator.IterateRows( this.Configuration, interest, diff --git a/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs index 9680dd0ac4..8128d01196 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs @@ -15,8 +15,8 @@ internal sealed class KernelSamplingMap : IDisposable { private readonly MemoryAllocator allocator; private bool isDisposed; - private IMemoryOwner yOffsets; - private IMemoryOwner xOffsets; + private IMemoryOwner? yOffsets; + private IMemoryOwner? xOffsets; /// /// Initializes a new instance of the class. @@ -64,10 +64,10 @@ public void BuildSamplingOffsetMap(int kernelHeight, int kernelWidth, Rectangle } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetRowOffsetSpan() => this.yOffsets.GetSpan(); + public Span GetRowOffsetSpan() => this.yOffsets!.GetSpan(); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetColumnOffsetSpan() => this.xOffsets.GetSpan(); + public Span GetColumnOffsetSpan() => this.xOffsets!.GetSpan(); /// public void Dispose() diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs index 310384d854..d900b2746a 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetector2DKernel.cs @@ -87,7 +87,7 @@ public EdgeDetector2DKernel(DenseMatrix kernelX, DenseMatrix kerne => !(left == right); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is EdgeDetector2DKernel kernel && this.Equals(kernel); /// diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs index 9f26e68e99..0c456eb88e 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorCompassKernel.cs @@ -134,7 +134,7 @@ public EdgeDetectorCompassKernel( => !(left == right); /// - public override bool Equals(object obj) => obj is EdgeDetectorCompassKernel kernel && this.Equals(kernel); + public override bool Equals(object? obj) => obj is EdgeDetectorCompassKernel kernel && this.Equals(kernel); /// public bool Equals(EdgeDetectorCompassKernel other) => this.North.Equals(other.North) && this.NorthWest.Equals(other.NorthWest) && this.West.Equals(other.West) && this.SouthWest.Equals(other.SouthWest) && this.South.Equals(other.South) && this.SouthEast.Equals(other.SouthEast) && this.East.Equals(other.East) && this.NorthEast.Equals(other.NorthEast); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs index 30b6001d2a..42a0c1cfe8 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Kernels/EdgeDetectorKernel.cs @@ -63,7 +63,7 @@ public EdgeDetectorKernel(DenseMatrix kernelXY) => !(left == right); /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is EdgeDetectorKernel kernel && this.Equals(kernel); /// diff --git a/src/ImageSharp/Processing/Processors/Convolution/MedianBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/MedianBlurProcessor{TPixel}.cs index 4f0c2a36c9..fa66bcb558 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/MedianBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/MedianBlurProcessor{TPixel}.cs @@ -42,7 +42,7 @@ protected override void OnFrameApply(ImageFrame source) MedianRowOperation operation = new( interest, targetPixels, - source.PixelBuffer, + source.PixelBuffer!, map, kernelSize, this.Configuration, @@ -53,6 +53,6 @@ protected override void OnFrameApply(ImageFrame source) operationBounds, in operation); - Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); + Buffer2D.SwapOrCopyContent(source.PixelBuffer!, targetPixels); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Parameters/BokehBlurParameters.cs b/src/ImageSharp/Processing/Processors/Convolution/Parameters/BokehBlurParameters.cs index bfc61a5549..cb92dce4a7 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Parameters/BokehBlurParameters.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Parameters/BokehBlurParameters.cs @@ -36,7 +36,7 @@ public bool Equals(BokehBlurParameters other) } /// - public override bool Equals(object obj) => obj is BokehBlurParameters other && this.Equals(other); + public override bool Equals(object? obj) => obj is BokehBlurParameters other && this.Equals(other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs index b4bd7b7972..6c869a62f5 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs @@ -105,7 +105,7 @@ public void ApplyQuantizationDither( int offsetY = bounds.Top; int offsetX = bounds.Left; float scale = quantizer.Options.DitherScale; - Buffer2D sourceBuffer = source.PixelBuffer; + Buffer2D sourceBuffer = source.PixelBuffer!; for (int y = bounds.Top; y < bounds.Bottom; y++) { @@ -135,7 +135,7 @@ public void ApplyPaletteDither( ThrowDefaultInstance(); } - Buffer2D sourceBuffer = source.PixelBuffer; + Buffer2D sourceBuffer = source.PixelBuffer!; float scale = processor.DitherScale; for (int y = bounds.Top; y < bounds.Bottom; y++) { @@ -173,7 +173,7 @@ internal TPixel Dither( int offset = this.offset; DenseMatrix matrix = this.matrix; - Buffer2D imageBuffer = image.PixelBuffer; + Buffer2D imageBuffer = image.PixelBuffer!; // Loop through and distribute the error amongst neighboring pixels. for (int row = 0, targetY = y; row < matrix.Rows; row++, targetY++) @@ -211,7 +211,7 @@ internal TPixel Dither( } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is ErrorDither dither && this.Equals(dither); /// @@ -219,8 +219,8 @@ public bool Equals(ErrorDither other) => this.offset == other.offset && this.matrix.Equals(other.matrix); /// - public bool Equals(IDither other) - => this.Equals((object)other); + public bool Equals(IDither? other) + => this.Equals((object?)other); /// public override int GetHashCode() diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs index 4d012de02c..1ead4daf53 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs @@ -118,7 +118,7 @@ public void ApplyQuantizationDither( int spread = CalculatePaletteSpread(destination.Palette.Length); float scale = quantizer.Options.DitherScale; - Buffer2D sourceBuffer = source.PixelBuffer; + Buffer2D sourceBuffer = source.PixelBuffer!; for (int y = bounds.Top; y < bounds.Bottom; y++) { @@ -149,7 +149,7 @@ public void ApplyPaletteDither( int spread = CalculatePaletteSpread(processor.Palette.Length); float scale = processor.DitherScale; - Buffer2D sourceBuffer = source.PixelBuffer; + Buffer2D sourceBuffer = source.PixelBuffer!; for (int y = bounds.Top; y < bounds.Bottom; y++) { @@ -199,7 +199,7 @@ internal TPixel Dither( } /// - public override bool Equals(object obj) + public override bool Equals(object? obj) => obj is OrderedDither dither && this.Equals(dither); /// @@ -208,8 +208,8 @@ public bool Equals(OrderedDither other) => this.thresholdMatrix.Equals(other.thresholdMatrix) && this.modulusX == other.modulusX && this.modulusY == other.modulusY; /// - public bool Equals(IDither other) - => this.Equals((object)other); + public bool Equals(IDither? other) + => this.Equals((object?)other); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs index f436343183..6c18e7c1a8 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor{TPixel}.cs @@ -65,7 +65,6 @@ protected override void Dispose(bool disposing) this.ditherProcessor.Dispose(); } - this.paletteOwner = null; base.Dispose(disposing); } diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs index 3206f7a3cb..784fe8feab 100644 --- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -64,7 +64,7 @@ public IImageProcessor CreatePixelSpecificProcessor(Configur { var visitor = new ProcessorFactoryVisitor(configuration, this, source, sourceRectangle); this.Image.AcceptVisitor(visitor); - return visitor.Result; + return visitor.Result!; } private class ProcessorFactoryVisitor : IImageVisitor @@ -83,7 +83,7 @@ public ProcessorFactoryVisitor(Configuration configuration, DrawImageProcessor d this.sourceRectangle = sourceRectangle; } - public IImageProcessor Result { get; private set; } + public IImageProcessor? Result { get; private set; } public void Visit(Image image) where TPixelFg : unmanaged, IPixel diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs index ac0d367515..1270a7f750 100644 --- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs +++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs @@ -98,7 +98,7 @@ protected override void OnFrameApply(ImageFrame source) "Cannot draw image because the source image does not overlap the target image."); } - var operation = new RowOperation(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity); + var operation = new RowOperation(source.PixelBuffer!, targetImage.Frames.RootFrame.PixelBuffer!, blender, configuration, minX, width, locationY, targetX, this.Opacity); ParallelRowIterator.IterateRows( configuration, workingRect, diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs index 67964f0ebd..5fb4e3311c 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs @@ -40,13 +40,13 @@ protected override void OnFrameApply(ImageFrame source) source.CopyTo(targetPixels); - RowIntervalOperation operation = new(this.SourceRectangle, targetPixels, source.PixelBuffer, this.Configuration, brushSize >> 1, this.definition.Levels); + RowIntervalOperation operation = new(this.SourceRectangle, targetPixels, source.PixelBuffer!, this.Configuration, brushSize >> 1, this.definition.Levels); ParallelRowIterator.IterateRowIntervals( this.Configuration, this.SourceRectangle, in operation); - Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); + Buffer2D.SwapOrCopyContent(source.PixelBuffer!, targetPixels); } /// diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs index e8c7468911..dc8cefba65 100644 --- a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs +++ b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs @@ -49,7 +49,7 @@ public PixelRowDelegateProcessor( protected override void OnFrameApply(ImageFrame source) { var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - var operation = new RowOperation(interest.X, source.PixelBuffer, this.Configuration, this.modifiers, this.rowDelegate); + var operation = new RowOperation(interest.X, source.PixelBuffer!, this.Configuration, this.modifiers, this.rowDelegate); ParallelRowIterator.IterateRows( this.Configuration, diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs index 68000ba3e8..af63239c64 100644 --- a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs @@ -45,7 +45,7 @@ protected override void OnFrameApply(ImageFrame source) Parallel.ForEach( range, this.Configuration.GetParallelOptions(), - new RowOperation(interest, size, source.PixelBuffer).Invoke); + new RowOperation(interest, size, source.PixelBuffer!).Invoke); } private readonly struct RowOperation diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs index e61b528efb..5ca52f07c7 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs @@ -35,7 +35,7 @@ public FilterProcessor(Configuration configuration, FilterProcessor definition, protected override void OnFrameApply(ImageFrame source) { var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - var operation = new RowOperation(interest.X, source.PixelBuffer, this.definition.Matrix, this.Configuration); + var operation = new RowOperation(interest.X, source.PixelBuffer!, this.definition.Matrix, this.Configuration); ParallelRowIterator.IterateRows( this.Configuration, diff --git a/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs index 30ffa7899d..dc2d395782 100644 --- a/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/OpaqueProcessor{TPixel}.cs @@ -25,7 +25,7 @@ protected override void OnFrameApply(ImageFrame source) { var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - var operation = new OpaqueRowOperation(this.Configuration, source.PixelBuffer, interest); + var operation = new OpaqueRowOperation(this.Configuration, source.PixelBuffer!, interest); ParallelRowIterator.IterateRows(this.Configuration, interest, in operation); } diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs index e2272db039..6fcbe9e551 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs @@ -78,37 +78,37 @@ protected override void OnFrameApply(ImageFrame source) yStart += tileHeight; } - var operation = new RowIntervalOperation(cdfData, tileYStartPositions, tileWidth, tileHeight, tileCount, halfTileWidth, luminanceLevels, source.PixelBuffer); + var operation = new RowIntervalOperation(cdfData, tileYStartPositions, tileWidth, tileHeight, tileCount, halfTileWidth, luminanceLevels, source.PixelBuffer!); ParallelRowIterator.IterateRowIntervals( this.Configuration, new Rectangle(0, 0, sourceWidth, tileYStartPositions.Count), in operation); // Fix left column - ProcessBorderColumn(source.PixelBuffer, cdfData, 0, sourceHeight, this.Tiles, tileHeight, xStart: 0, xEnd: halfTileWidth, luminanceLevels); + ProcessBorderColumn(source.PixelBuffer!, cdfData, 0, sourceHeight, this.Tiles, tileHeight, xStart: 0, xEnd: halfTileWidth, luminanceLevels); // Fix right column int rightBorderStartX = ((this.Tiles - 1) * tileWidth) + halfTileWidth; - ProcessBorderColumn(source.PixelBuffer, cdfData, this.Tiles - 1, sourceHeight, this.Tiles, tileHeight, xStart: rightBorderStartX, xEnd: sourceWidth, luminanceLevels); + ProcessBorderColumn(source.PixelBuffer!, cdfData, this.Tiles - 1, sourceHeight, this.Tiles, tileHeight, xStart: rightBorderStartX, xEnd: sourceWidth, luminanceLevels); // Fix top row - ProcessBorderRow(source.PixelBuffer, cdfData, 0, sourceWidth, this.Tiles, tileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + ProcessBorderRow(source.PixelBuffer!, cdfData, 0, sourceWidth, this.Tiles, tileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); // Fix bottom row int bottomBorderStartY = ((this.Tiles - 1) * tileHeight) + halfTileHeight; - ProcessBorderRow(source.PixelBuffer, cdfData, this.Tiles - 1, sourceWidth, this.Tiles, tileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + ProcessBorderRow(source.PixelBuffer!, cdfData, this.Tiles - 1, sourceWidth, this.Tiles, tileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); // Left top corner - ProcessCornerTile(source.PixelBuffer, cdfData, 0, 0, xStart: 0, xEnd: halfTileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + ProcessCornerTile(source.PixelBuffer!, cdfData, 0, 0, xStart: 0, xEnd: halfTileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); // Left bottom corner - ProcessCornerTile(source.PixelBuffer, cdfData, 0, this.Tiles - 1, xStart: 0, xEnd: halfTileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + ProcessCornerTile(source.PixelBuffer!, cdfData, 0, this.Tiles - 1, xStart: 0, xEnd: halfTileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); // Right top corner - ProcessCornerTile(source.PixelBuffer, cdfData, this.Tiles - 1, 0, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + ProcessCornerTile(source.PixelBuffer!, cdfData, this.Tiles - 1, 0, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); // Right bottom corner - ProcessCornerTile(source.PixelBuffer, cdfData, this.Tiles - 1, this.Tiles - 1, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + ProcessCornerTile(source.PixelBuffer!, cdfData, this.Tiles - 1, this.Tiles - 1, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); } } @@ -514,7 +514,7 @@ public void CalculateLookupTables(ImageFrame source, HistogramEqualizati this.tileWidth, this.tileHeight, this.luminanceLevels, - source.PixelBuffer); + source.PixelBuffer!); ParallelRowIterator.IterateRowIntervals( this.configuration, diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs index 3aaf2631ae..e7806f4ae3 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs @@ -157,7 +157,7 @@ protected override void OnFrameApply(ImageFrame source) parallelOptions, bottomBorderOperation.Invoke); - Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); + Buffer2D.SwapOrCopyContent(source.PixelBuffer!, targetPixels); } /// @@ -222,7 +222,7 @@ private static void CopyPixelRow( return; } - CopyPixelRowFast(source.PixelBuffer, rowPixels, x, y, tileWidth, configuration); + CopyPixelRowFast(source.PixelBuffer!, rowPixels, x, y, tileWidth, configuration); } /// @@ -354,7 +354,7 @@ public void Invoke(int x) { if (this.useFastPath) { - CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, dy, this.swInfos.TileWidth, this.configuration); + CopyPixelRowFast(this.source.PixelBuffer!, pixelRow, x - this.swInfos.HalfTileWidth, dy, this.swInfos.TileWidth, this.configuration); } else { @@ -388,7 +388,7 @@ public void Invoke(int x) // Remove top most row from the histogram, mirroring rows which exceeds the borders. if (this.useFastPath) { - CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, y - this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); + CopyPixelRowFast(this.source.PixelBuffer!, pixelRow, x - this.swInfos.HalfTileWidth, y - this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); } else { @@ -400,7 +400,7 @@ public void Invoke(int x) // Add new bottom row to the histogram, mirroring rows which exceeds the borders. if (this.useFastPath) { - CopyPixelRowFast(this.source.PixelBuffer, pixelRow, x - this.swInfos.HalfTileWidth, y + this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); + CopyPixelRowFast(this.source.PixelBuffer!, pixelRow, x - this.swInfos.HalfTileWidth, y + this.swInfos.HalfTileWidth, this.swInfos.TileWidth, this.configuration); } else { diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs index 59c37373ea..4a758cbeee 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs @@ -51,7 +51,7 @@ protected override void OnFrameApply(ImageFrame source) using IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean); // Build the histogram of the grayscale levels. - var grayscaleOperation = new GrayscaleLevelsRowOperation(interest, histogramBuffer, source.PixelBuffer, this.LuminanceLevels); + var grayscaleOperation = new GrayscaleLevelsRowOperation(interest, histogramBuffer, source.PixelBuffer!, this.LuminanceLevels); ParallelRowIterator.IterateRows( this.Configuration, interest, @@ -74,7 +74,7 @@ ref MemoryMarshal.GetReference(histogram), float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin; // Apply the cdf to each pixel of the image - var cdfOperation = new CdfApplicationRowOperation(interest, cdfBuffer, source.PixelBuffer, this.LuminanceLevels, numberOfPixelsMinusCdfMin); + var cdfOperation = new CdfApplicationRowOperation(interest, cdfBuffer, source.PixelBuffer!, this.LuminanceLevels, numberOfPixelsMinusCdfMin); ParallelRowIterator.IterateRows( this.Configuration, interest, diff --git a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs index 1e43458253..2f6334c756 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs @@ -48,7 +48,7 @@ protected override void OnFrameApply(ImageFrame source) PixelBlender blender = PixelOperations.Instance.GetPixelBlender(graphicsOptions); - var operation = new RowOperation(configuration, interest, blender, amount, colors, source.PixelBuffer); + var operation = new RowOperation(configuration, interest, blender, amount, colors, source.PixelBuffer!); ParallelRowIterator.IterateRows( configuration, interest, diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs index c431650b33..84604f890b 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs @@ -54,7 +54,7 @@ protected override void OnFrameApply(ImageFrame source) using IMemoryOwner rowColors = allocator.Allocate(interest.Width); rowColors.GetSpan().Fill(glowColor); - var operation = new RowOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source.PixelBuffer); + var operation = new RowOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source.PixelBuffer!); ParallelRowIterator.IterateRows( configuration, interest, diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs index c69b6360d5..8e8ab77175 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs @@ -62,7 +62,7 @@ protected override void OnFrameApply(ImageFrame source) using IMemoryOwner rowColors = allocator.Allocate(interest.Width); rowColors.GetSpan().Fill(vignetteColor); - var operation = new RowOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source.PixelBuffer); + var operation = new RowOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source.PixelBuffer!); ParallelRowIterator.IterateRows( configuration, interest, diff --git a/src/ImageSharp/Processing/Processors/Quantization/DefaultPixelSamplingStrategy.cs b/src/ImageSharp/Processing/Processors/Quantization/DefaultPixelSamplingStrategy.cs index 9da1d98e3b..caf888aa2b 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/DefaultPixelSamplingStrategy.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/DefaultPixelSamplingStrategy.cs @@ -60,7 +60,7 @@ public IEnumerable> EnumeratePixelRegions(Image frame in image.Frames) { - yield return frame.PixelBuffer.GetRegion(); + yield return frame.PixelBuffer!.GetRegion(); } } else @@ -97,7 +97,7 @@ Buffer2DRegion GetRow(int pos) { int frameIdx = pos / image.Height; int y = pos % image.Height; - return image.Frames[frameIdx].PixelBuffer.GetRegion(0, y, image.Width, 1); + return image.Frames[frameIdx].PixelBuffer!.GetRegion(0, y, image.Width, 1); } } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/ExtensivePixelSamplingStrategy.cs b/src/ImageSharp/Processing/Processors/Quantization/ExtensivePixelSamplingStrategy.cs index 580227c2d7..85e68e7373 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/ExtensivePixelSamplingStrategy.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/ExtensivePixelSamplingStrategy.cs @@ -17,7 +17,7 @@ public IEnumerable> EnumeratePixelRegions(Image frame in image.Frames) { - yield return frame.PixelBuffer.GetRegion(); + yield return frame.PixelBuffer!.GetRegion(); } } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs index bbe8e4113f..7088221959 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs @@ -28,7 +28,7 @@ public struct OctreeQuantizer : IQuantizer private readonly Octree octree; private IMemoryOwner paletteOwner; private ReadOnlyMemory palette; - private EuclideanPixelMap pixelMap; + private EuclideanPixelMap? pixelMap; private readonly bool isDithering; private bool isDisposed; @@ -142,7 +142,7 @@ public readonly byte GetQuantizedColor(TPixel color, out TPixel match) // pixel and a black one. if (this.isDithering || color.Equals(default)) { - return (byte)this.pixelMap.GetClosestColor(color, out match); + return (byte)this.pixelMap!.GetClosestColor(color, out match); } ref TPixel paletteRef = ref MemoryMarshal.GetReference(this.palette.Span); @@ -158,7 +158,6 @@ public void Dispose() { this.isDisposed = true; this.paletteOwner?.Dispose(); - this.paletteOwner = null; this.pixelMap?.Dispose(); this.pixelMap = null; } @@ -182,7 +181,7 @@ private sealed class Octree /// /// Store the last node quantized /// - private OctreeNode previousNode; + private OctreeNode? previousNode; /// /// Cache the previous color quantized @@ -311,7 +310,7 @@ private void Reduce() // Reduce the node most recently added to the list at level 'index' OctreeNode node = this.ReducibleNodes[index]; - this.ReducibleNodes[index] = node.NextReducible; + this.ReducibleNodes[index] = node.NextReducible!; // Decrement the leaf count after reducing the node this.Leaves -= node.Reduce(); @@ -329,7 +328,7 @@ public sealed class OctreeNode /// /// Pointers to any child nodes /// - private readonly OctreeNode[] children; + private readonly OctreeNode?[]? children; /// /// Flag indicating that this is a leaf node @@ -394,7 +393,7 @@ public OctreeNode(int level, int colorBits, Octree octree) /// /// Gets the next reducible node /// - public OctreeNode NextReducible + public OctreeNode? NextReducible { [MethodImpl(InliningOptions.ShortMethod)] get; @@ -422,12 +421,12 @@ public void AddColor(ref Rgba32 color, int colorBits, int level, Octree octree) // Go to the next level down in the tree int index = GetColorIndex(ref color, level); - OctreeNode child = this.children[index]; + OctreeNode? child = this.children?[index]; if (child is null) { // Create a new child node and store it in the array child = new OctreeNode(level + 1, colorBits, octree); - this.children[index] = child; + this.children![index] = child; } // Add the color to the child node @@ -447,7 +446,7 @@ public int Reduce() // Loop through all children and add their information to this node for (int index = 0; index < 8; index++) { - OctreeNode child = this.children[index]; + OctreeNode? child = this.children?[index]; if (child != null) { this.red += child.red; @@ -455,7 +454,7 @@ public int Reduce() this.blue += child.blue; this.pixelCount += child.pixelCount; ++childNodes; - this.children[index] = null; + this.children![index] = null; } } @@ -494,7 +493,7 @@ public void ConstructPalette(Span palette, ref int index) // Loop through children looking for leaves for (int i = 0; i < 8; i++) { - this.children[i]?.ConstructPalette(palette, ref index); + this.children![i]?.ConstructPalette(palette, ref index); } } } @@ -516,7 +515,7 @@ public int GetPaletteIndex(ref Rgba32 pixel, int level) } int colorIndex = GetColorIndex(ref pixel, level); - OctreeNode child = this.children[colorIndex]; + OctreeNode? child = this.children![colorIndex]; int index = 0; if (child != null) diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs index bb565affef..686cf45250 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs @@ -68,6 +68,5 @@ public readonly byte GetQuantizedColor(TPixel color, out TPixel match) public void Dispose() { this.pixelMap?.Dispose(); - this.pixelMap = null; } } diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs index f8be91bc2b..10c1771bb5 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs @@ -41,7 +41,7 @@ protected override void OnFrameApply(ImageFrame source) ReadOnlySpan paletteSpan = quantized.Palette.Span; int offsetY = interest.Top; int offsetX = interest.Left; - Buffer2D sourceBuffer = source.PixelBuffer; + Buffer2D sourceBuffer = source.PixelBuffer!; for (int y = interest.Y; y < interest.Height; y++) { diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs index 04e8124037..2f7e9572e8 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs @@ -51,7 +51,7 @@ public static IndexedImageFrame BuildPaletteAndQuantizeFrame( Guard.NotNull(source, nameof(source)); var interest = Rectangle.Intersect(source.Bounds(), bounds); - Buffer2DRegion region = source.PixelBuffer.GetRegion(interest); + Buffer2DRegion region = source.PixelBuffer!.GetRegion(interest); // Collect the palette. Required before the second pass runs. quantizer.AddPaletteColors(region); @@ -121,7 +121,7 @@ private static void SecondPass( where TPixel : unmanaged, IPixel { IDither dither = quantizer.Options.Dither; - Buffer2D sourceBuffer = source.PixelBuffer; + Buffer2D sourceBuffer = source.PixelBuffer!; if (dither is null) { diff --git a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs index 1b39c85af6..0119558bff 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs @@ -75,7 +75,7 @@ internal struct WuQuantizer : IQuantizer private ReadOnlyMemory palette; private int maxColors; private readonly Box[] colorCube; - private EuclideanPixelMap pixelMap; + private EuclideanPixelMap? pixelMap; private readonly bool isDithering; private bool isDisposed; @@ -174,7 +174,7 @@ public readonly byte GetQuantizedColor(TPixel color, out TPixel match) { if (this.isDithering) { - return (byte)this.pixelMap.GetClosestColor(color, out match); + return (byte)this.pixelMap!.GetClosestColor(color, out match); } Rgba32 rgba = default; @@ -202,9 +202,6 @@ public void Dispose() this.momentsOwner?.Dispose(); this.tagsOwner?.Dispose(); this.paletteOwner?.Dispose(); - this.momentsOwner = null; - this.tagsOwner = null; - this.paletteOwner = null; this.pixelMap?.Dispose(); this.pixelMap = null; } @@ -868,7 +865,7 @@ private struct Box : IEquatable public int Volume; /// - public override readonly bool Equals(object obj) + public override readonly bool Equals(object? obj) => obj is Box box && this.Equals(box); diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs index 1d82dd12ad..bf07a0769d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs @@ -50,7 +50,7 @@ protected override void OnFrameApply(ImageFrame source, ImageFrame : TransformProcessor, IR private readonly Size destinationSize; private readonly Matrix3x2 transformMatrix; private readonly IResampler resampler; - private ImageFrame source; - private ImageFrame destination; + private ImageFrame? source; + private ImageFrame? destination; /// /// Initializes a new instance of the class. @@ -52,8 +52,8 @@ public void ApplyTransform(in TResampler sampler) where TResampler : struct, IResampler { Configuration configuration = this.Configuration; - ImageFrame source = this.source; - ImageFrame destination = this.destination; + ImageFrame? source = this.source; + ImageFrame? destination = this.destination; Matrix3x2 matrix = this.transformMatrix; // Handle transforms that result in output identical to the original. @@ -61,9 +61,9 @@ public void ApplyTransform(in TResampler sampler) if (matrix.Equals(Matrix3x2.Identity)) { // The clone will be blank here copy all the pixel data over - var interest = Rectangle.Intersect(this.SourceRectangle, destination.Bounds()); - Buffer2DRegion sourceBuffer = source.PixelBuffer.GetRegion(interest); - Buffer2DRegion destbuffer = destination.PixelBuffer.GetRegion(interest); + var interest = Rectangle.Intersect(this.SourceRectangle, destination!.Bounds()); + Buffer2DRegion sourceBuffer = source!.PixelBuffer!.GetRegion(interest); + Buffer2DRegion destbuffer = destination.PixelBuffer!.GetRegion(interest); for (int y = 0; y < sourceBuffer.Height; y++) { sourceBuffer.DangerousGetRowSpan(y).CopyTo(destbuffer.DangerousGetRowSpan(y)); @@ -78,9 +78,9 @@ public void ApplyTransform(in TResampler sampler) if (sampler is NearestNeighborResampler) { var nnOperation = new NNAffineOperation( - source.PixelBuffer, + source!.PixelBuffer!, Rectangle.Intersect(this.SourceRectangle, source.Bounds()), - destination.PixelBuffer, + destination!.PixelBuffer!, matrix); ParallelRowIterator.IterateRows( @@ -93,9 +93,9 @@ public void ApplyTransform(in TResampler sampler) var operation = new AffineOperation( configuration, - source.PixelBuffer, + source!.PixelBuffer!, Rectangle.Intersect(this.SourceRectangle, source.Bounds()), - destination.PixelBuffer, + destination!.PixelBuffer!, in sampler, matrix); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs index 6952e561fb..6d70bd3797 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs @@ -88,7 +88,7 @@ private static ushort GetExifOrientation(Image source) return ExifOrientationMode.Unknown; } - IExifValue value = source.Metadata.ExifProfile.GetValue(ExifTag.Orientation); + IExifValue? value = source.Metadata.ExifProfile.GetValue(ExifTag.Orientation); if (value is null) { return ExifOrientationMode.Unknown; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs index 11befd5dac..666e894133 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs @@ -35,7 +35,7 @@ protected override void OnFrameApply(ImageFrame source) { // No default needed as we have already set the pixels. case FlipMode.Vertical: - FlipX(source.PixelBuffer, this.Configuration); + FlipX(source.PixelBuffer!, this.Configuration); break; case FlipMode.Horizontal: FlipY(source, this.Configuration); @@ -72,7 +72,7 @@ private static void FlipX(Buffer2D source, Configuration configuration) /// The configuration. private static void FlipY(ImageFrame source, Configuration configuration) { - var operation = new RowOperation(source.PixelBuffer); + var operation = new RowOperation(source.PixelBuffer!); ParallelRowIterator.IterateRows( configuration, source.Bounds(), diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs index 440becf833..1c68c21aae 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs @@ -19,8 +19,8 @@ internal class ProjectiveTransformProcessor : TransformProcessor private readonly Size destinationSize; private readonly IResampler resampler; private readonly Matrix4x4 transformMatrix; - private ImageFrame source; - private ImageFrame destination; + private ImageFrame? source; + private ImageFrame? destination; /// /// Initializes a new instance of the class. @@ -52,8 +52,8 @@ public void ApplyTransform(in TResampler sampler) where TResampler : struct, IResampler { Configuration configuration = this.Configuration; - ImageFrame source = this.source; - ImageFrame destination = this.destination; + ImageFrame? source = this.source; + ImageFrame? destination = this.destination; Matrix4x4 matrix = this.transformMatrix; // Handle transforms that result in output identical to the original. @@ -61,9 +61,9 @@ public void ApplyTransform(in TResampler sampler) if (matrix.Equals(Matrix4x4.Identity)) { // The clone will be blank here copy all the pixel data over - var interest = Rectangle.Intersect(this.SourceRectangle, destination.Bounds()); - Buffer2DRegion sourceBuffer = source.PixelBuffer.GetRegion(interest); - Buffer2DRegion destbuffer = destination.PixelBuffer.GetRegion(interest); + var interest = Rectangle.Intersect(this.SourceRectangle, destination!.Bounds()); + Buffer2DRegion sourceBuffer = source!.PixelBuffer!.GetRegion(interest); + Buffer2DRegion destbuffer = destination.PixelBuffer!.GetRegion(interest); for (int y = 0; y < sourceBuffer.Height; y++) { sourceBuffer.DangerousGetRowSpan(y).CopyTo(destbuffer.DangerousGetRowSpan(y)); @@ -78,9 +78,9 @@ public void ApplyTransform(in TResampler sampler) if (sampler is NearestNeighborResampler) { var nnOperation = new NNProjectiveOperation( - source.PixelBuffer, + source!.PixelBuffer!, Rectangle.Intersect(this.SourceRectangle, source.Bounds()), - destination.PixelBuffer, + destination!.PixelBuffer!, matrix); ParallelRowIterator.IterateRows( @@ -93,9 +93,9 @@ public void ApplyTransform(in TResampler sampler) var operation = new ProjectiveOperation( configuration, - source.PixelBuffer, + source!.PixelBuffer!, Rectangle.Intersect(this.SourceRectangle, source.Bounds()), - destination.PixelBuffer, + destination!.PixelBuffer!, in sampler, matrix); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor{TPixel}.cs index ac50337f6e..7b451784a8 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 @@ protected override void OnFrameApply(ImageFrame source, ImageFrame protected override void AfterImageApply(Image destination) { - ExifProfile profile = destination.Metadata.ExifProfile; + ExifProfile? profile = destination.Metadata.ExifProfile; if (profile is null) { return; @@ -130,7 +130,7 @@ private bool OptimizedApply( /// The configuration. private static void Rotate180(ImageFrame source, ImageFrame destination, Configuration configuration) { - var operation = new Rotate180RowOperation(source.Width, source.Height, source.PixelBuffer, destination.PixelBuffer); + var operation = new Rotate180RowOperation(source.Width, source.Height, source.PixelBuffer!, destination.PixelBuffer!); ParallelRowIterator.IterateRows( configuration, source.Bounds(), @@ -145,7 +145,7 @@ private static void Rotate180(ImageFrame source, ImageFrame dest /// The configuration. private static void Rotate270(ImageFrame source, ImageFrame destination, Configuration configuration) { - var operation = new Rotate270RowIntervalOperation(destination.Bounds(), source.Width, source.Height, source.PixelBuffer, destination.PixelBuffer); + var operation = new Rotate270RowIntervalOperation(destination.Bounds(), source.Width, source.Height, source.PixelBuffer!, destination.PixelBuffer!); ParallelRowIterator.IterateRowIntervals( configuration, source.Bounds(), @@ -160,7 +160,7 @@ private static void Rotate270(ImageFrame source, ImageFrame dest /// The configuration. private static void Rotate90(ImageFrame source, ImageFrame destination, Configuration configuration) { - var operation = new Rotate90RowOperation(destination.Bounds(), source.Width, source.Height, source.PixelBuffer, destination.PixelBuffer); + var operation = new Rotate90RowOperation(destination.Bounds(), source.Width, source.Height, source.PixelBuffer!, destination.PixelBuffer!); ParallelRowIterator.IterateRows( configuration, source.Bounds(), diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs index 8cff50f55b..cc5c3a5a8d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs @@ -410,7 +410,7 @@ private static (Size Size, Rectangle Rectangle) CalculateManualRectangle( ThrowInvalid("Manual resizing requires a target location and size."); } - Rectangle targetRectangle = options.TargetRectangle.Value; + Rectangle targetRectangle = options.TargetRectangle!.Value; int targetX = targetRectangle.X; int targetY = targetRectangle.Y; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index 9011ec3944..f1a349b6ab 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -20,7 +20,7 @@ internal class ResizeProcessor : TransformProcessor, IResampling private readonly int destinationHeight; private readonly IResampler resampler; private readonly Rectangle destinationRectangle; - private Image destination; + private Image? destination; public ResizeProcessor(Configuration configuration, ResizeProcessor definition, Image source, Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) @@ -55,7 +55,7 @@ public void ApplyTransform(in TResampler sampler) { Configuration configuration = this.Configuration; Image source = this.Source; - Image destination = this.destination; + Image? destination = this.destination; Rectangle sourceRectangle = this.SourceRectangle; Rectangle destinationRectangle = this.destinationRectangle; bool compand = this.options.Compand; @@ -65,7 +65,7 @@ public void ApplyTransform(in TResampler sampler) && this.options.PadColor != default; // Handle resize dimensions identical to the original - if (source.Width == destination.Width + if (source.Width == destination!.Width && source.Height == destination.Height && sourceRectangle == destinationRectangle) { @@ -164,8 +164,8 @@ private static void ApplyNNResizeFrameTransform( interest, widthFactor, heightFactor, - source.PixelBuffer, - destination.PixelBuffer); + source.PixelBuffer!, + destination.PixelBuffer!); ParallelRowIterator.IterateRows( configuration, @@ -204,7 +204,7 @@ private static void ApplyResizeFrameTransform( premultiplyAlpha &= needsPremultiplication; PixelConversionModifiers conversionModifiers = GetModifiers(compand, premultiplyAlpha); - Buffer2DRegion sourceRegion = source.PixelBuffer.GetRegion(sourceRectangle); + Buffer2DRegion sourceRegion = source.PixelBuffer!.GetRegion(sourceRectangle); // To reintroduce parallel processing, we would launch multiple workers // for different row intervals of the image. @@ -219,7 +219,7 @@ private static void ApplyResizeFrameTransform( worker.Initialize(); var workingInterval = new RowInterval(interest.Top, interest.Bottom); - worker.FillDestinationPixels(workingInterval, destination.PixelBuffer); + worker.FillDestinationPixels(workingInterval, destination.PixelBuffer!); } private readonly struct NNRowOperation : IRowOperation diff --git a/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs index 1ea2156c8f..35419100d6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs @@ -27,7 +27,7 @@ protected override void OnFrameApply(ImageFrame source, ImageFrame sourceBuffer = source.PixelBuffer; + Buffer2D sourceBuffer = source.PixelBuffer!; for (p.Y = 0; p.Y < source.Height; p.Y++) { Span rowSpan = sourceBuffer.DangerousGetRowSpan(p.Y); diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs index 8e7452679b..172d7d677f 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.Tests/Image/ImageFrameCollectionTests.Generic.cs b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs index 28c4f686b0..decd38b19b 100644 --- a/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs +++ b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.Generic.cs @@ -40,7 +40,7 @@ public void AddNewFrame_Frame_FramesNotBeNull() using ImageFrame addedFrame = this.Collection.AddFrame((ImageFrame)null); }); - Assert.StartsWith("Parameter \"frame\" must be not null.", ex.Message); + Assert.StartsWith("Value cannot be null. (Parameter 'frame", ex.Message); } [Fact] @@ -54,7 +54,7 @@ public void AddNewFrame_PixelBuffer_DataMustNotBeNull() using ImageFrame addedFrame = this.Collection.AddFrame(data); }); - Assert.StartsWith("Parameter \"source\" must be not null.", ex.Message); + Assert.StartsWith("Value cannot be null. (Parameter 'source'", ex.Message); } [Fact] @@ -91,7 +91,7 @@ public void InsertNewFrame_FramesNotBeNull() using ImageFrame insertedFrame = this.Collection.InsertFrame(1, null); }); - Assert.StartsWith("Parameter \"frame\" must be not null.", ex.Message); + Assert.StartsWith("Value cannot be null. (Parameter 'frame'", ex.Message); } [Fact] diff --git a/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs index 6e394d5925..25ad579fe4 100644 --- a/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs +++ b/tests/ImageSharp.Tests/Image/ImageFrameCollectionTests.NonGeneric.cs @@ -85,7 +85,7 @@ public void AddNewFrame_Frame_FramesNotBeNull() this.Collection.AddFrame(null); }); - Assert.StartsWith("Parameter \"source\" must be not null.", ex.Message); + Assert.StartsWith("Value cannot be null. (Parameter 'source'", ex.Message); } [Fact] @@ -109,7 +109,7 @@ public void InsertNewFrame_FramesNotBeNull() this.Collection.InsertFrame(1, null); }); - Assert.StartsWith("Parameter \"source\" must be not null.", ex.Message); + Assert.StartsWith("Value cannot be null. (Parameter 'source'", ex.Message); } [Fact] diff --git a/tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.cs b/tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.cs index 316150c305..9541e501db 100644 --- a/tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.cs +++ b/tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using System.Buffers; using System.Collections; using SixLabors.ImageSharp.Memory;