From 07d116d8d1bfe0c2230add108f953f5eeb6fcfe3 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Tue, 17 Jan 2023 13:27:37 +0100 Subject: [PATCH 01/37] Remove #nullable disable from ExifProfile --- .../Common/Helpers/UnitConverter.cs | 2 +- .../Profiles/Exif/ExifEncodedStringHelpers.cs | 4 +-- .../Metadata/Profiles/Exif/ExifProfile.cs | 31 ++++++++++--------- .../Metadata/Profiles/Exif/ExifReader.cs | 27 ++++++++-------- .../Exif/ExifTagDescriptionAttribute.cs | 9 +++--- .../Metadata/Profiles/Exif/ExifWriter.cs | 28 +++++++++-------- .../Exif/Values/ExifArrayValue{TValueType}.cs | 7 ++--- .../Metadata/Profiles/Exif/Values/ExifByte.cs | 2 +- .../Profiles/Exif/Values/ExifByteArray.cs | 2 +- .../Profiles/Exif/Values/ExifDouble.cs | 2 +- .../Profiles/Exif/Values/ExifEncodedString.cs | 2 +- .../Profiles/Exif/Values/ExifFloat.cs | 2 +- .../Metadata/Profiles/Exif/Values/ExifLong.cs | 2 +- .../Profiles/Exif/Values/ExifLong8.cs | 2 +- .../Profiles/Exif/Values/ExifLong8Array.cs | 2 +- .../Profiles/Exif/Values/ExifNumber.cs | 2 +- .../Profiles/Exif/Values/ExifNumberArray.cs | 2 +- .../Profiles/Exif/Values/ExifRational.cs | 2 +- .../Profiles/Exif/Values/ExifRationalArray.cs | 2 +- .../Profiles/Exif/Values/ExifShort.cs | 2 +- .../Profiles/Exif/Values/ExifShortArray.cs | 2 +- .../Profiles/Exif/Values/ExifSignedByte.cs | 2 +- .../Profiles/Exif/Values/ExifSignedShort.cs | 2 +- .../Exif/Values/ExifSignedShortArray.cs | 2 +- .../Profiles/Exif/Values/ExifString.cs | 4 +-- .../Profiles/Exif/Values/ExifUcs2String.cs | 6 ++-- .../Profiles/Exif/Values/ExifValue.cs | 11 +++---- .../Profiles/Exif/Values/ExifValues.cs | 11 +++---- .../Exif/Values/ExifValue{TValueType}.cs | 18 ++++------- .../Profiles/Exif/Values/IExifValue.cs | 4 +-- .../Exif/Values/IExifValue{TValueType}.cs | 2 +- .../Linear/AutoOrientProcessor{TPixel}.cs | 2 +- 32 files changed, 97 insertions(+), 103 deletions(-) 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/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index 8d6723c28c..bfe991f833 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers.Binary; using System.Text; @@ -27,7 +26,8 @@ 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) ?? + throw new InvalidOperationException(); public static bool IsEncodedString(ExifTagValue tag) => tag switch { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs index dbe19d8b6e..9a41fb6a4e 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs @@ -1,7 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -14,12 +15,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 @@ -35,7 +36,7 @@ public sealed class ExifProfile : IDeepCloneable /// Initializes a new instance of the class. /// public ExifProfile() - : this((byte[])null) + : this((byte[]?)null) { } @@ -43,7 +44,7 @@ public sealed class ExifProfile : IDeepCloneable /// 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; @@ -110,6 +111,7 @@ public sealed class ExifProfile : IDeepCloneable /// /// Gets the values of this EXIF profile. /// + [MemberNotNull(nameof(values))] public IReadOnlyList Values { get @@ -125,7 +127,7 @@ public sealed class ExifProfile : IDeepCloneable /// /// The . /// - public Image CreateThumbnail() => this.CreateThumbnail(); + public Image? CreateThumbnail() => this.CreateThumbnail(); /// /// Returns the thumbnail in the EXIF profile when available. @@ -134,7 +136,7 @@ public sealed class ExifProfile : IDeepCloneable /// /// The . /// - public Image CreateThumbnail() + public Image? CreateThumbnail() where TPixel : unmanaged, IPixel { this.InitializeValues(); @@ -161,9 +163,9 @@ public sealed class ExifProfile : IDeepCloneable /// 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; } @@ -203,7 +205,7 @@ public sealed class ExifProfile : IDeepCloneable /// Converts this instance to a byte array. /// /// The - public byte[] ToByteArray() + public byte[]? ToByteArray() { if (this.values is null) { @@ -227,7 +229,7 @@ public sealed class ExifProfile : IDeepCloneable /// /// 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) { @@ -245,7 +247,7 @@ public sealed class ExifProfile : IDeepCloneable /// /// 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) { @@ -256,7 +258,7 @@ public sealed class ExifProfile : IDeepCloneable } } - ExifValue newExifValue = ExifValues.Create(tag); + ExifValue? newExifValue = ExifValues.Create(tag); if (newExifValue is null) { throw new NotSupportedException(); @@ -278,7 +280,7 @@ public sealed class ExifProfile : IDeepCloneable private void SyncResolution(ExifTag tag, double resolution) { - IExifValue value = this.GetValue(tag); + IExifValue? value = this.GetValue(tag); if (value is null) { @@ -294,6 +296,7 @@ public sealed class ExifProfile : IDeepCloneable 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 a93973a8dc..7b989c8d8a 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Buffers.Binary; @@ -20,7 +19,7 @@ internal class ExifReader : BaseExifReader { } - public ExifReader(byte[] exifData, MemoryAllocator allocator) + public ExifReader(byte[] exifData, MemoryAllocator? allocator) : base(new MemoryStream(exifData ?? throw new ArgumentNullException(nameof(exifData))), allocator) { } @@ -90,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; @@ -219,7 +218,7 @@ internal abstract class BaseExifReader 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); } } @@ -255,7 +254,7 @@ internal abstract class BaseExifReader 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) { @@ -390,7 +389,7 @@ internal abstract class BaseExifReader 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) { @@ -414,7 +413,7 @@ internal abstract class BaseExifReader } 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); } } @@ -443,7 +442,7 @@ internal abstract class BaseExifReader 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), @@ -471,12 +470,12 @@ internal abstract class BaseExifReader } 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)) { @@ -510,7 +509,7 @@ internal abstract class BaseExifReader 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 b9e74e246d..da5214087f 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Reflection; @@ -29,10 +28,10 @@ internal sealed class ExifTagDescriptionAttribute : Attribute /// /// 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) { @@ -41,11 +40,11 @@ internal sealed class ExifTagDescriptionAttribute : Attribute 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 d156cbee36..26442b2c41 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers.Binary; @@ -16,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; @@ -45,8 +44,8 @@ internal sealed class ExifWriter { 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); @@ -160,7 +159,7 @@ internal sealed class ExifWriter 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; @@ -179,7 +178,9 @@ internal sealed class ExifWriter return ifdValues[index]; } - ExifValue result = ExifValues.Create(offset); + ExifValue? result = ExifValues.Create(offset); + Guard.NotNull(result); + ifdValues.Add(result); return result; @@ -219,7 +220,7 @@ internal sealed class ExifWriter private static bool HasValue(IExifValue exifValue) { - object value = exifValue.GetValue(); + object? value = exifValue.GetValue(); if (value is null) { return false; @@ -270,11 +271,11 @@ internal sealed class ExifWriter 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) @@ -284,7 +285,7 @@ internal sealed class ExifWriter 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) @@ -298,7 +299,7 @@ internal sealed class ExifWriter 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); } @@ -308,7 +309,7 @@ internal sealed class ExifWriter private int WriteData(uint startIndex, List values, Span destination, int offset) { - if (this.dataOffsets.Count == 0) + if (this.dataOffsets is null || this.dataOffsets.Count == 0) { return offset; } @@ -428,7 +429,8 @@ internal sealed class ExifWriter internal static int WriteValue(IExifValue exifValue, Span destination, int offset) { - object value = exifValue.GetValue(); + object? value = exifValue.GetValue(); + Guard.NotNull(value); if (ExifUcs2StringHelpers.IsUcs2Tag((ExifTagValue)(ushort)exifValue.Tag)) { diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifArrayValue{TValueType}.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifArrayValue{TValueType}.cs index 97f795c0fd..64b8d23137 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifArrayValue{TValueType}.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifArrayValue{TValueType}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable namespace SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -23,11 +22,11 @@ internal abstract class ExifArrayValue : ExifValue, IExifValue 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 @@ internal sealed class ExifByte : ExifValue 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 @@ internal sealed class ExifByteArray : ExifArrayValue 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 @@ internal sealed class ExifDouble : ExifValue 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 @@ internal sealed class ExifEncodedString : ExifValue 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 @@ internal sealed class ExifFloat : ExifValue 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 @@ internal sealed class ExifLong : ExifValue 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 @@ internal sealed class ExifLong8 : ExifValue 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 @@ internal sealed class ExifLong8Array : ExifArrayValue } } - 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 @@ internal sealed class ExifNumber : ExifValue 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 @@ internal sealed class ExifNumberArray : ExifArrayValue } } - 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 @@ internal sealed class ExifRational : ExifValue 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 @@ internal sealed class ExifRationalArray : ExifArrayValue 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 @@ internal sealed class ExifShort : ExifValue 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 @@ internal sealed class ExifShortArray : ExifArrayValue 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 @@ internal sealed class ExifSignedByte : ExifValue 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..6726febef0 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShort.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedShort.cs @@ -21,7 +21,7 @@ internal sealed class ExifSignedShort : ExifValue 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 @@ internal sealed class ExifSignedShortArray : ExifArrayValue 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 @@ internal sealed class ExifString : ExifValue 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 @@ internal sealed class ExifUcs2String : ExifValue 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 b28e404dfc..eacb41cfb3 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Runtime.CompilerServices; @@ -28,7 +27,7 @@ internal abstract class ExifValue : IExifValue, IEquatable else { // All array types are value types so Clone() is sufficient here. - var array = (Array)other.GetValue(); + Array? array = (Array?)other.GetValue(); this.TrySetValue(array?.Clone()); } } @@ -43,7 +42,7 @@ internal abstract class ExifValue : IExifValue, IEquatable 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) { @@ -69,14 +68,14 @@ internal abstract class ExifValue : IExifValue, IEquatable } [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 783da40253..8aa54c3a40 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs @@ -1,18 +1,17 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable 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) { @@ -49,7 +48,7 @@ internal static partial class ExifValues } } - 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 0face8401f..6442f26846 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable namespace SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -21,16 +20,16 @@ internal abstract class ExifValue : ExifValue, IExifValue /// 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) { @@ -49,14 +48,9 @@ internal abstract class ExifValue : ExifValue, IExifValue /// 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/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 @@ internal class AutoOrientProcessor : ImageProcessor 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; From 9a92a145d77a89a5c9148dee8b73623bd9757575 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 21 Jan 2023 17:41:51 +1000 Subject: [PATCH 02/37] Add extensions and use overloads --- .../Extensions/Drawing/DrawImageExtensions.cs | 216 +++++++++++++----- .../Processors/Drawing/DrawImageProcessor.cs | 6 +- .../DrawImageProcessor{TPixelBg,TPixelFg}.cs | 4 +- 3 files changed, 168 insertions(+), 58 deletions(-) diff --git a/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs index 2cb8dc3211..eba107545d 100644 --- a/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs @@ -23,14 +23,26 @@ public static class DrawImageExtensions Image image, float opacity) { - var options = source.GetGraphicsOptions(); - return source.ApplyProcessor( - new DrawImageProcessor( - image, - Point.Empty, - options.ColorBlendingMode, - options.AlphaCompositionMode, - opacity)); + GraphicsOptions options = source.GetGraphicsOptions(); + return DrawImage(source, image, options.ColorBlendingMode, options.AlphaCompositionMode, opacity); + } + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The structure that specifies the portion of the image to draw. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Rectangle rectangle, + float opacity) + { + GraphicsOptions options = source.GetGraphicsOptions(); + return DrawImage(source, image, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity); } /// @@ -45,14 +57,25 @@ public static class DrawImageExtensions this IImageProcessingContext source, Image image, PixelColorBlendingMode colorBlending, - float opacity) => - source.ApplyProcessor( - new DrawImageProcessor( - image, - Point.Empty, - colorBlending, - source.GetGraphicsOptions().AlphaCompositionMode, - opacity)); + float opacity) + => DrawImage(source, image, Point.Empty, colorBlending, opacity); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The structure that specifies the portion of the image to draw. + /// The blending mode. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Rectangle rectangle, + PixelColorBlendingMode colorBlending, + float opacity) + => DrawImage(source, image, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); /// /// Draws the given image together with the current one by blending their pixels. @@ -68,8 +91,27 @@ public static class DrawImageExtensions Image image, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, - float opacity) => - source.ApplyProcessor(new DrawImageProcessor(image, Point.Empty, colorBlending, alphaComposition, opacity)); + float opacity) + => DrawImage(source, image, Point.Empty, colorBlending, alphaComposition, opacity); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The structure that specifies the portion of the image to draw. + /// The color blending mode. + /// The alpha composition mode. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Rectangle rectangle, + PixelColorBlendingMode colorBlending, + PixelAlphaCompositionMode alphaComposition, + float opacity) + => DrawImage(source, image, Point.Empty, rectangle, colorBlending, alphaComposition, opacity); /// /// Draws the given image together with the current one by blending their pixels. @@ -81,14 +123,23 @@ public static class DrawImageExtensions public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, - GraphicsOptions options) => - source.ApplyProcessor( - new DrawImageProcessor( - image, - Point.Empty, - options.ColorBlendingMode, - options.AlphaCompositionMode, - options.BlendPercentage)); + GraphicsOptions options) + => DrawImage(source, image, Point.Empty, options); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The structure that specifies the portion of the image to draw. + /// The options, including the blending type and blending amount. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Rectangle rectangle, + GraphicsOptions options) + => DrawImage(source, image, Point.Empty, rectangle, options); /// /// Draws the given image together with the current one by blending their pixels. @@ -104,14 +155,28 @@ public static class DrawImageExtensions Point location, float opacity) { - var options = source.GetGraphicsOptions(); - return source.ApplyProcessor( - new DrawImageProcessor( - image, - location, - options.ColorBlendingMode, - options.AlphaCompositionMode, - opacity)); + GraphicsOptions options = source.GetGraphicsOptions(); + return DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, opacity); + } + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The structure that specifies the portion of the image to draw. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + Rectangle rectangle, + float opacity) + { + GraphicsOptions options = source.GetGraphicsOptions(); + return DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, opacity); } /// @@ -128,14 +193,59 @@ public static class DrawImageExtensions Image image, Point location, PixelColorBlendingMode colorBlending, - float opacity) => - source.ApplyProcessor( - new DrawImageProcessor( - image, - location, - colorBlending, - source.GetGraphicsOptions().AlphaCompositionMode, - opacity)); + float opacity) + => DrawImage(source, image, location, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The structure that specifies the portion of the image to draw. + /// The color blending to apply. + /// The opacity of the image to blend. Must be between 0 and 1. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + Rectangle rectangle, + PixelColorBlendingMode colorBlending, + float opacity) + => DrawImage(source, image, location, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The options containing the blend mode and opacity. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + GraphicsOptions options) + => DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage); + + /// + /// Draws the given image together with the current one by blending their pixels. + /// + /// The image this method extends. + /// The image to blend with the currently processing image. + /// The location to draw the blended image. + /// The structure that specifies the portion of the image to draw. + /// The options containing the blend mode and opacity. + /// The . + public static IImageProcessingContext DrawImage( + this IImageProcessingContext source, + Image image, + Point location, + Rectangle rectangle, + GraphicsOptions options) + => DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage); /// /// Draws the given image together with the current one by blending their pixels. @@ -153,8 +263,8 @@ public static class DrawImageExtensions Point location, PixelColorBlendingMode colorBlending, PixelAlphaCompositionMode alphaComposition, - float opacity) => - source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); + float opacity) + => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); /// /// Draws the given image together with the current one by blending their pixels. @@ -162,18 +272,20 @@ public static class DrawImageExtensions /// The image this method extends. /// The image to blend with the currently processing image. /// The location to draw the blended image. - /// The options containing the blend mode and opacity. + /// The structure that specifies the portion of the image to draw. + /// The color blending to apply. + /// The alpha composition mode. + /// The opacity of the image to blend. Must be between 0 and 1. /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, Point location, - GraphicsOptions options) => + Rectangle rectangle, + PixelColorBlendingMode colorBlending, + PixelAlphaCompositionMode alphaComposition, + float opacity) => source.ApplyProcessor( - new DrawImageProcessor( - image, - location, - options.ColorBlendingMode, - options.AlphaCompositionMode, - options.BlendPercentage)); + new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity), + rectangle); } diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs index b7d5b42f8a..9de4f862b8 100644 --- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -63,7 +63,7 @@ public class DrawImageProcessor : IImageProcessor public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixelBg : unmanaged, IPixel { - var visitor = new ProcessorFactoryVisitor(configuration, this, source, sourceRectangle); + ProcessorFactoryVisitor visitor = new(configuration, this, source, sourceRectangle); this.Image.AcceptVisitor(visitor); return visitor.Result; } @@ -88,8 +88,7 @@ public class DrawImageProcessor : IImageProcessor public void Visit(Image image) where TPixelFg : unmanaged, IPixel - { - this.Result = new DrawImageProcessor( + => this.Result = new DrawImageProcessor( this.configuration, image, this.source, @@ -98,6 +97,5 @@ public class DrawImageProcessor : IImageProcessor this.definition.ColorBlendingMode, this.definition.AlphaCompositionMode, this.definition.Opacity); - } } } diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs index 82e639f1bd..436a447972 100644 --- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs +++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs @@ -89,7 +89,7 @@ internal class DrawImageProcessor : ImageProcessor int width = maxX - minX; - var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); + Rectangle workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY); // Not a valid operation because rectangle does not overlap with this image. if (workingRect.Width <= 0 || workingRect.Height <= 0) @@ -98,7 +98,7 @@ internal class DrawImageProcessor : ImageProcessor "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); + DrawImageProcessor.RowOperation operation = new(source.PixelBuffer, targetImage.Frames.RootFrame.PixelBuffer, blender, configuration, minX, width, locationY, targetX, this.Opacity); ParallelRowIterator.IterateRows( configuration, workingRect, From a39ac71837145bc78265e03faa6f67974d497341 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Sat, 21 Jan 2023 10:10:48 +0100 Subject: [PATCH 03/37] Change GetThumbnail to TryGetThumbnail --- .../Metadata/Profiles/Exif/ExifProfile.cs | 31 +++++++++++++------ .../Profiles/Exif/ExifProfileTests.cs | 7 +++-- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs index 9a41fb6a4e..ebe20cff6b 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs @@ -124,36 +124,47 @@ public sealed class ExifProfile : IDeepCloneable /// /// Returns the thumbnail in the EXIF profile when available. /// + /// The thumbnail /// - /// The . + /// True, if there is a thumbnail otherwise false. /// - public Image? CreateThumbnail() => this.CreateThumbnail(); + public bool TryCreateThumbnail([NotNullWhen(true)] out Image? image) + { + if (this.TryCreateThumbnail(out Image? innerimage)) + { + image = innerimage; + return true; + } + + image = null; + return false; + } /// /// Returns the thumbnail in the EXIF profile when available. /// /// The pixel format. - /// - /// The . - /// - public Image? CreateThumbnail() + /// The thumbnail. + /// True, if there is a thumbnail otherwise false. + public bool TryCreateThumbnail([NotNullWhen(true)] out Image? image) where TPixel : unmanaged, IPixel { this.InitializeValues(); - + image = null; if (this.thumbnailOffset == 0 || this.thumbnailLength == 0) { - return null; + return false; } if (this.data is null || this.data.Length < (this.thumbnailOffset + this.thumbnailLength)) { - return null; + return false; } using (var memStream = new MemoryStream(this.data, this.thumbnailOffset, this.thumbnailLength)) { - return Image.Load(memStream); + image = Image.Load(memStream); + return true; } } diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs index 26f777ae72..873bc9ca2c 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs @@ -345,13 +345,14 @@ public class ExifProfileTests ExifProfile profile = GetExifProfile(); TestProfile(profile); - - using Image thumbnail = profile.CreateThumbnail(); + bool retVal = profile.TryCreateThumbnail(out Image thumbnail); + Assert.True(retVal); Assert.NotNull(thumbnail); Assert.Equal(256, thumbnail.Width); Assert.Equal(170, thumbnail.Height); - using Image genericThumbnail = profile.CreateThumbnail(); + retVal = profile.TryCreateThumbnail(out Image genericThumbnail); + Assert.True(retVal); Assert.NotNull(genericThumbnail); Assert.Equal(256, genericThumbnail.Width); Assert.Equal(170, genericThumbnail.Height); From 06f413107f15d19be085f222088acade7dc60e78 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Sat, 21 Jan 2023 13:11:52 +0100 Subject: [PATCH 04/37] Convert to TryGetValue --- .../Common/Helpers/UnitConverter.cs | 9 +- .../Formats/Jpeg/JpegDecoderCore.cs | 7 +- .../Formats/Tiff/TiffBitsPerSample.cs | 2 +- .../Formats/Tiff/TiffDecoderCore.cs | 32 +++++-- .../Tiff/TiffDecoderMetadataCreator.cs | 22 +++-- .../Formats/Tiff/TiffDecoderOptionsParser.cs | 94 +++++++++++++++---- .../Formats/Tiff/TiffEncoderCore.cs | 2 - .../Formats/Tiff/TiffFrameMetadata.cs | 26 +++-- .../Formats/Tiff/TiffThrowHelper.cs | 9 ++ .../Metadata/Profiles/Exif/ExifProfile.cs | 19 ++-- .../Linear/AutoOrientProcessor{TPixel}.cs | 3 +- .../Transforms/TransformProcessorHelpers.cs | 4 +- .../Formats/Jpg/JpegDecoderTests.Metadata.cs | 1 + .../Formats/Png/PngMetadataTests.cs | 1 + .../Formats/Tiff/BigTiffDecoderTests.cs | 1 + .../Formats/Tiff/TiffEncoderBaseTester.cs | 1 + .../Formats/Tiff/TiffMetadataTests.cs | 9 +- .../Formats/WebP/WebpMetaDataTests.cs | 1 + .../Metadata/ImageMetadataTests.cs | 1 + .../Profiles/Exif/ExifProfileTests.cs | 5 +- .../Exif/ExifTagDescriptionAttributeTests.cs | 1 + .../Metadata/Profiles/Exif/ExifValueTests.cs | 4 +- .../Transforms/TransformsHelpersTest.cs | 1 + .../TestUtilities/ExifProfileExtensions.cs | 18 ++++ 24 files changed, 207 insertions(+), 66 deletions(-) create mode 100644 tests/ImageSharp.Tests/TestUtilities/ExifProfileExtensions.cs diff --git a/src/ImageSharp/Common/Helpers/UnitConverter.cs b/src/ImageSharp/Common/Helpers/UnitConverter.cs index 983d86a711..45dbe41cb9 100644 --- a/src/ImageSharp/Common/Helpers/UnitConverter.cs +++ b/src/ImageSharp/Common/Helpers/UnitConverter.cs @@ -91,10 +91,13 @@ internal static class UnitConverter [MethodImpl(InliningOptions.ShortMethod)] public static PixelResolutionUnit ExifProfileToResolutionUnit(ExifProfile profile) { - IExifValue? resolution = profile.GetValue(ExifTag.ResolutionUnit); + if (profile.TryGetValue(ExifTag.ResolutionUnit, out IExifValue? resolution)) + { + // EXIF is 1, 2, 3 so we minus "1" off the result. + return (PixelResolutionUnit)(byte)(resolution.Value - 1); + } - // EXIF is 1, 2, 3 so we minus "1" off the result. - return resolution is null ? DefaultResolutionUnit : (PixelResolutionUnit)(byte)(resolution.Value - 1); + return DefaultResolutionUnit; } /// diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 511ec1ba1d..77ea4e86fc 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -705,9 +705,12 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals private double GetExifResolutionValue(ExifTag tag) { - IExifValue resolution = this.Metadata.ExifProfile.GetValue(tag); + if (this.Metadata.ExifProfile.TryGetValue(tag, out IExifValue resolution)) + { + return resolution.Value.ToDouble(); + } - return resolution is null ? 0 : resolution.Value.ToDouble(); + return 0; } /// diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs index fb35ef2de3..382faa3874 100644 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerSample.cs @@ -82,7 +82,7 @@ public readonly struct TiffBitsPerSample : IEquatable /// The value to parse. /// The tiff bits per sample. /// True, if the value could be parsed. - public static bool TryParse(ushort[] value, out TiffBitsPerSample sample) + public static bool TryParse(ushort[]? value, out TiffBitsPerSample sample) { if (value is null || value.Length == 0) { diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index e74c53e22d..87784d1cb4 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -276,9 +276,15 @@ internal class TiffDecoderCore : IImageDecoderInternals private void DecodeImageWithStrips(ExifProfile tags, ImageFrame frame, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { - int rowsPerStrip = tags.GetValue(ExifTag.RowsPerStrip) != null - ? (int)tags.GetValue(ExifTag.RowsPerStrip).Value - : TiffConstants.RowsPerStripInfinity; + int rowsPerStrip; + if (tags.TryGetValue(ExifTag.RowsPerStrip, out IExifValue value)) + { + rowsPerStrip = (int)value.Value; + } + else + { + rowsPerStrip = TiffConstants.RowsPerStripInfinity; + } Array stripOffsetsArray = (Array)tags.GetValueInternal(ExifTag.StripOffsets).GetValue(); Array stripByteCountsArray = (Array)tags.GetValueInternal(ExifTag.StripByteCounts).GetValue(); @@ -320,8 +326,18 @@ internal class TiffDecoderCore : IImageDecoderInternals int width = pixels.Width; int height = pixels.Height; - int tileWidth = (int)tags.GetValue(ExifTag.TileWidth).Value; - int tileLength = (int)tags.GetValue(ExifTag.TileLength).Value; + if (!tags.TryGetValue(ExifTag.TileWidth, out IExifValue valueWidth)) + { + ArgumentNullException.ThrowIfNull(valueWidth); + } + + if (!tags.TryGetValue(ExifTag.TileWidth, out IExifValue valueLength)) + { + ArgumentNullException.ThrowIfNull(valueLength); + } + + int tileWidth = (int)valueWidth.Value; + int tileLength = (int)valueLength.Value; int tilesAcross = (width + tileWidth - 1) / tileWidth; int tilesDown = (height + tileLength - 1) / tileLength; @@ -775,8 +791,7 @@ internal class TiffDecoderCore : IImageDecoderInternals /// The image width. private static int GetImageWidth(ExifProfile exifProfile) { - IExifValue width = exifProfile.GetValue(ExifTag.ImageWidth); - if (width == null) + if (!exifProfile.TryGetValue(ExifTag.ImageWidth, out IExifValue width)) { TiffThrowHelper.ThrowImageFormatException("The TIFF image frame is missing the ImageWidth"); } @@ -793,8 +808,7 @@ internal class TiffDecoderCore : IImageDecoderInternals /// The image height. private static int GetImageHeight(ExifProfile exifProfile) { - IExifValue height = exifProfile.GetValue(ExifTag.ImageLength); - if (height == null) + if (!exifProfile.TryGetValue(ExifTag.ImageLength, out IExifValue height)) { 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 b6ce718f38..1a6c9dd7de 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderMetadataCreator.cs @@ -38,14 +38,12 @@ internal static class TiffDecoderMetadataCreator frameMetaData.IptcProfile = new IptcProfile(iptcBytes); } - IExifValue xmpProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.XMP); - if (xmpProfileBytes != null) + if (frameMetaData.ExifProfile.TryGetValue(ExifTag.XMP, out IExifValue xmpProfileBytes)) { frameMetaData.XmpProfile = new XmpProfile(xmpProfileBytes.Value); } - IExifValue iccProfileBytes = frameMetaData.ExifProfile.GetValue(ExifTag.IccProfile); - if (iccProfileBytes != null) + if (frameMetaData.ExifProfile.TryGetValue(ExifTag.IccProfile, out IExifValue iccProfileBytes)) { frameMetaData.IccProfile = new IccProfile(iccProfileBytes.Value); } @@ -70,16 +68,20 @@ internal static class TiffDecoderMetadataCreator 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(); - if (horizontalResolution != null) + + if (exifProfile is null) + { + return; + } + + if (exifProfile.TryGetValue(ExifTag.XResolution, out IExifValue horizontalResolution)) { - imageMetaData.HorizontalResolution = horizontalResolution.Value; + imageMetaData.HorizontalResolution = horizontalResolution.Value.ToDouble(); } - double? verticalResolution = exifProfile?.GetValue(ExifTag.YResolution)?.Value.ToDouble(); - if (verticalResolution != null) + if (exifProfile.TryGetValue(ExifTag.YResolution, out IExifValue verticalResolution)) { - imageMetaData.VerticalResolution = verticalResolution.Value; + imageMetaData.VerticalResolution = verticalResolution.Value.ToDouble(); } } diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs index f20263602d..a13fb58de7 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderOptionsParser.cs @@ -42,7 +42,16 @@ internal static class TiffDecoderOptionsParser } } - TiffFillOrder fillOrder = (TiffFillOrder?)exifProfile.GetValue(ExifTag.FillOrder)?.Value ?? TiffFillOrder.MostSignificantBitFirst; + TiffFillOrder fillOrder; + if (exifProfile.TryGetValue(ExifTag.FillOrder, out IExifValue value)) + { + fillOrder = (TiffFillOrder)value.Value; + } + else + { + fillOrder = TiffFillOrder.MostSignificantBitFirst; + } + if (fillOrder == TiffFillOrder.LeastSignificantBitFirst && frameMetadata.BitsPerPixel != TiffBitsPerPixel.Bit1) { TiffThrowHelper.ThrowNotSupported("The lower-order bits of the byte FillOrder is only supported in combination with 1bit per pixel bicolor tiff's."); @@ -53,10 +62,10 @@ internal static class TiffDecoderOptionsParser TiffThrowHelper.ThrowNotSupported("TIFF images with FloatingPoint horizontal predictor are not supported."); } - TiffSampleFormat[] sampleFormats = exifProfile.GetValue(ExifTag.SampleFormat)?.Value?.Select(a => (TiffSampleFormat)a).ToArray(); TiffSampleFormat? sampleFormat = null; - if (sampleFormats != null) + if (exifProfile.TryGetValue(ExifTag.SampleFormat, out var formatValue)) { + TiffSampleFormat[] sampleFormats = formatValue.Value.Select(a => (TiffSampleFormat)a).ToArray(); sampleFormat = sampleFormats[0]; foreach (TiffSampleFormat format in sampleFormats) { @@ -67,7 +76,12 @@ internal static class TiffDecoderOptionsParser } } - ushort[] ycbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value; + ushort[] ycbcrSubSampling = null; + if (exifProfile.TryGetValue(ExifTag.YCbCrSubsampling, out IExifValue subSamplingValue)) + { + ycbcrSubSampling = subSamplingValue.Value; + } + if (ycbcrSubSampling != null && ycbcrSubSampling.Length != 2) { TiffThrowHelper.ThrowImageFormatException("Invalid YCbCrSubsampling, expected 2 values."); @@ -78,23 +92,52 @@ internal static class TiffDecoderOptionsParser TiffThrowHelper.ThrowImageFormatException("ChromaSubsampleVert shall always be less than or equal to ChromaSubsampleHoriz."); } - if (exifProfile.GetValue(ExifTag.StripRowCounts)?.Value != null) + if (exifProfile.TryGetValue(ExifTag.StripRowCounts, out _)) { TiffThrowHelper.ThrowNotSupported("Variable-sized strips are not supported."); } - options.PlanarConfiguration = (TiffPlanarConfiguration?)exifProfile.GetValue(ExifTag.PlanarConfiguration)?.Value ?? DefaultPlanarConfiguration; + if (exifProfile.TryGetValue(ExifTag.PlanarConfiguration, out IExifValue planarValue)) + { + options.PlanarConfiguration = (TiffPlanarConfiguration)planarValue.Value; + } + else + { + options.PlanarConfiguration = DefaultPlanarConfiguration; + } + options.Predictor = frameMetadata.Predictor ?? TiffPredictor.None; options.PhotometricInterpretation = frameMetadata.PhotometricInterpretation ?? TiffPhotometricInterpretation.Rgb; options.SampleFormat = sampleFormat ?? TiffSampleFormat.UnsignedInteger; options.BitsPerPixel = frameMetadata.BitsPerPixel != null ? (int)frameMetadata.BitsPerPixel.Value : (int)TiffBitsPerPixel.Bit24; options.BitsPerSample = frameMetadata.BitsPerSample ?? new TiffBitsPerSample(0, 0, 0); - options.ReferenceBlackAndWhite = exifProfile.GetValue(ExifTag.ReferenceBlackWhite)?.Value; - options.YcbcrCoefficients = exifProfile.GetValue(ExifTag.YCbCrCoefficients)?.Value; - options.YcbcrSubSampling = exifProfile.GetValue(ExifTag.YCbCrSubsampling)?.Value; + + if (exifProfile.TryGetValue(ExifTag.ReferenceBlackWhite, out IExifValue blackWhiteValue)) + { + options.ReferenceBlackAndWhite = blackWhiteValue.Value; + } + + if (exifProfile.TryGetValue(ExifTag.YCbCrCoefficients, out IExifValue coefficientsValue)) + { + options.YcbcrCoefficients = coefficientsValue.Value; + } + + if (exifProfile.TryGetValue(ExifTag.YCbCrSubsampling, out IExifValue ycbrSubSamplingValue)) + { + options.YcbcrSubSampling = ycbrSubSamplingValue.Value; + } + options.FillOrder = fillOrder; - options.JpegTables = exifProfile.GetValue(ExifTag.JPEGTables)?.Value; - options.OldJpegCompressionStartOfImageMarker = exifProfile.GetValue(ExifTag.JPEGInterchangeFormat)?.Value; + + if (exifProfile.TryGetValue(ExifTag.JPEGTables, out IExifValue jpegTablesValue)) + { + options.JpegTables = jpegTablesValue.Value; + } + + if (exifProfile.TryGetValue(ExifTag.JPEGInterchangeFormat, out IExifValue jpegInterchangeFormatValue)) + { + options.OldJpegCompressionStartOfImageMarker = jpegInterchangeFormatValue.Value; + } options.ParseColorType(exifProfile); options.ParseCompression(frameMetadata.Compression, exifProfile); @@ -394,9 +437,9 @@ internal static class TiffDecoderOptionsParser case TiffPhotometricInterpretation.PaletteColor: { - options.ColorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value; - if (options.ColorMap != null) + if (exifProfile.TryGetValue(ExifTag.ColorMap, out IExifValue value)) { + options.ColorMap = value.Value; if (options.BitsPerSample.Channels != 1) { TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported."); @@ -414,7 +457,11 @@ internal static class TiffDecoderOptionsParser case TiffPhotometricInterpretation.YCbCr: { - options.ColorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value; + if (exifProfile.TryGetValue(ExifTag.ColorMap, out IExifValue value)) + { + options.ColorMap = value.Value; + } + if (options.BitsPerSample.Channels != 3) { TiffThrowHelper.ThrowNotSupported("The number of samples in the TIFF BitsPerSample entry is not supported for YCbCr images."); @@ -508,7 +555,15 @@ internal static class TiffDecoderOptionsParser case TiffCompression.CcittGroup3Fax: { options.CompressionType = TiffDecoderCompressionType.T4; - options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None; + + if (exifProfile.TryGetValue(ExifTag.T4Options, out IExifValue t4OptionsValue)) + { + options.FaxCompressionOptions = (FaxCompressionOptions)t4OptionsValue.Value; + } + else + { + options.FaxCompressionOptions = FaxCompressionOptions.None; + } break; } @@ -516,7 +571,14 @@ internal static class TiffDecoderOptionsParser case TiffCompression.CcittGroup4Fax: { options.CompressionType = TiffDecoderCompressionType.T6; - options.FaxCompressionOptions = exifProfile.GetValue(ExifTag.T4Options) != null ? (FaxCompressionOptions)exifProfile.GetValue(ExifTag.T4Options).Value : FaxCompressionOptions.None; + if (exifProfile.TryGetValue(ExifTag.T4Options, out IExifValue t4OptionsValue)) + { + options.FaxCompressionOptions = (FaxCompressionOptions)t4OptionsValue.Value; + } + else + { + options.FaxCompressionOptions = FaxCompressionOptions.None; + } break; } diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 8da2c26dee..3a4e71d3e8 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -164,8 +164,6 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals { cancellationToken.ThrowIfCancellationRequested(); - TiffNewSubfileType subfileType = (TiffNewSubfileType)(frame.Metadata.ExifProfile?.GetValue(ExifTag.SubfileType)?.Value ?? (int)TiffNewSubfileType.FullImage); - ifdMarker = this.WriteFrame(writer, frame, image.Metadata, metadataImage, ifdMarker); metadataImage = null; } diff --git a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs index 956213c231..5d0b85bf22 100644 --- a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs +++ b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -78,15 +77,30 @@ public class TiffFrameMetadata : IDeepCloneable { if (profile != null) { - if (TiffBitsPerSample.TryParse(profile.GetValue(ExifTag.BitsPerSample)?.Value, out TiffBitsPerSample bitsPerSample)) + if (profile.TryGetValue(ExifTag.BitsPerSample, out IExifValue? bitsPerSampleValue)) { - meta.BitsPerSample = bitsPerSample; + if (TiffBitsPerSample.TryParse(bitsPerSampleValue.Value, out TiffBitsPerSample bitsPerSample)) + { + meta.BitsPerSample = bitsPerSample; + } } meta.BitsPerPixel = meta.BitsPerSample?.BitsPerPixel(); - meta.Compression = (TiffCompression?)profile.GetValue(ExifTag.Compression)?.Value; - meta.PhotometricInterpretation = (TiffPhotometricInterpretation?)profile.GetValue(ExifTag.PhotometricInterpretation)?.Value; - meta.Predictor = (TiffPredictor?)profile.GetValue(ExifTag.Predictor)?.Value; + + if (profile.TryGetValue(ExifTag.Compression, out IExifValue? compressionValue)) + { + meta.Compression = (TiffCompression)compressionValue.Value; + } + + if (profile.TryGetValue(ExifTag.PhotometricInterpretation, out IExifValue? photometricInterpretationValue)) + { + meta.PhotometricInterpretation = (TiffPhotometricInterpretation)photometricInterpretationValue.Value; + } + + if (profile.TryGetValue(ExifTag.Predictor, out IExifValue? predictorValue)) + { + meta.Predictor = (TiffPredictor)predictorValue.Value; + } profile.RemoveValue(ExifTag.BitsPerSample); profile.RemoveValue(ExifTag.Compression); diff --git a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs index b2cc638ba0..3957ccb02f 100644 --- a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs +++ b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs @@ -1,21 +1,30 @@ // 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); + [DoesNotReturn] public static Exception NotSupportedDecompressor(string compressionType) => throw new NotSupportedException($"Not supported decoder compression method: {compressionType}"); + [DoesNotReturn] public static Exception NotSupportedCompressor(string compressionType) => throw new NotSupportedException($"Not supported encoder compression method: {compressionType}"); + [DoesNotReturn] public static Exception InvalidColorType(string colorType) => throw new NotSupportedException($"Invalid color type: {colorType}"); + [DoesNotReturn] public static Exception ThrowInvalidHeader() => throw new ImageFormatException("Invalid TIFF file header."); + [DoesNotReturn] public static void ThrowNotSupported(string message) => throw new NotSupportedException(message); + [DoesNotReturn] public static void ThrowArgumentException(string message) => throw new ArgumentException(message); } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs index ebe20cff6b..e14c88229d 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs @@ -172,12 +172,21 @@ public sealed class ExifProfile : IDeepCloneable /// Returns the value with the specified tag. /// /// The tag of the exif value. - /// The value with the specified tag. + /// The value with the specified tag. + /// True when found, otherwise false /// The data type of the tag. - public IExifValue? GetValue(ExifTag tag) + public bool TryGetValue(ExifTag tag, [NotNullWhen(true)] out IExifValue? exifValue) { IExifValue? value = this.GetValueInternal(tag); - return value is null ? null : (IExifValue)value; + + if (value is null) + { + exifValue = null; + return false; + } + + exifValue = (IExifValue)value; + return true; } /// @@ -291,9 +300,7 @@ public sealed class ExifProfile : IDeepCloneable private void SyncResolution(ExifTag tag, double resolution) { - IExifValue? value = this.GetValue(tag); - - if (value is null) + if (!this.TryGetValue(tag, out IExifValue? value)) { return; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs index 6d70bd3797..0ad6842128 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs @@ -88,8 +88,7 @@ internal class AutoOrientProcessor : ImageProcessor return ExifOrientationMode.Unknown; } - IExifValue? value = source.Metadata.ExifProfile.GetValue(ExifTag.Orientation); - if (value is null) + if (!source.Metadata.ExifProfile.TryGetValue(ExifTag.Orientation, out IExifValue? value)) { return ExifOrientationMode.Unknown; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs index 172d7d677f..0bb4920f0f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs @@ -26,12 +26,12 @@ internal static class TransformProcessorHelpers } // Only set the value if it already exists. - if (profile.GetValue(ExifTag.PixelXDimension) != null) + if (profile.TryGetValue(ExifTag.PixelXDimension, out _)) { profile.SetValue(ExifTag.PixelXDimension, image.Width); } - if (profile.GetValue(ExifTag.PixelYDimension) != null) + if (profile.TryGetValue(ExifTag.PixelYDimension, out _)) { profile.SetValue(ExifTag.PixelYDimension, image.Height); } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs index 7e0b1de82b..9bff30b6f4 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs @@ -8,6 +8,7 @@ using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg; diff --git a/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs index 9653a06564..d7a353665a 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs @@ -6,6 +6,7 @@ using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Formats.Png; diff --git a/tests/ImageSharp.Tests/Formats/Tiff/BigTiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/BigTiffDecoderTests.cs index 5c110844c3..8e90b1dd57 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/BigTiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/BigTiffDecoderTests.cs @@ -6,6 +6,7 @@ using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using static SixLabors.ImageSharp.Tests.TestImages.BigTiff; diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs index 6da0d4fd89..2a822e7054 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderBaseTester.cs @@ -6,6 +6,7 @@ using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff.Constants; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs index 2a809e895a..51c0b6ef7e 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs @@ -10,6 +10,7 @@ using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Iptc; using SixLabors.ImageSharp.Metadata.Profiles.Xmp; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; using static SixLabors.ImageSharp.Tests.TestImages.Tiff; namespace SixLabors.ImageSharp.Tests.Formats.Tiff; @@ -167,9 +168,9 @@ public class TiffMetadataTests Assert.Equal("Make", exifProfile.GetValue(ExifTag.Make).Value); Assert.Equal("Model", exifProfile.GetValue(ExifTag.Model).Value); Assert.Equal("ImageSharp", exifProfile.GetValue(ExifTag.Software).Value); - Assert.Null(exifProfile.GetValue(ExifTag.DateTime)?.Value); + Assert.Null(exifProfile.GetValue(ExifTag.DateTime, false)?.Value); Assert.Equal("Artist", exifProfile.GetValue(ExifTag.Artist).Value); - Assert.Null(exifProfile.GetValue(ExifTag.HostComputer)?.Value); + Assert.Null(exifProfile.GetValue(ExifTag.HostComputer, false)?.Value); Assert.Equal("Copyright", exifProfile.GetValue(ExifTag.Copyright).Value); Assert.Equal(4, exifProfile.GetValue(ExifTag.Rating).Value); Assert.Equal(75, exifProfile.GetValue(ExifTag.RatingPercent).Value); @@ -178,9 +179,9 @@ public class TiffMetadataTests Assert.Equal(expectedResolution, exifProfile.GetValue(ExifTag.YResolution).Value); Assert.Equal(new Number[] { 8u }, exifProfile.GetValue(ExifTag.StripOffsets)?.Value, new NumberComparer()); Assert.Equal(new Number[] { 285u }, exifProfile.GetValue(ExifTag.StripByteCounts)?.Value, new NumberComparer()); - Assert.Null(exifProfile.GetValue(ExifTag.ExtraSamples)?.Value); + Assert.Null(exifProfile.GetValue(ExifTag.ExtraSamples, false)?.Value); Assert.Equal(32u, exifProfile.GetValue(ExifTag.RowsPerStrip).Value); - Assert.Null(exifProfile.GetValue(ExifTag.SampleFormat)); + Assert.Null(exifProfile.GetValue(ExifTag.SampleFormat, false)); Assert.Equal(PixelResolutionUnit.PixelsPerInch, UnitConverter.ExifProfileToResolutionUnit(exifProfile)); ushort[] colorMap = exifProfile.GetValue(ExifTag.ColorMap)?.Value; Assert.NotNull(colorMap); diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs index c0c2e375f4..ab8fef60f7 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/WebpMetaDataTests.cs @@ -5,6 +5,7 @@ using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Webp; diff --git a/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs b/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs index 9b1e42d016..330b701474 100644 --- a/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs +++ b/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs @@ -4,6 +4,7 @@ using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Metadata; diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs index 873bc9ca2c..8072bebd77 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs @@ -7,6 +7,7 @@ using SixLabors.ImageSharp.Formats.Webp; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif; @@ -255,7 +256,7 @@ public class ExifProfileTests xResolution = image.Metadata.ExifProfile.GetValue(ExifTag.XResolution); Assert.Equal(new Rational(150.0), xResolution.Value); - referenceBlackWhite = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); + referenceBlackWhite = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite, false); Assert.Null(referenceBlackWhite); latitude = image.Metadata.ExifProfile.GetValue(ExifTag.GPSLatitude); @@ -300,7 +301,7 @@ public class ExifProfileTests Assert.NotNull(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace)); Assert.True(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace)); Assert.False(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace)); - Assert.Null(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace)); + Assert.Null(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace, false)); Assert.Equal(profileCount - 1, image.Metadata.ExifProfile.Values.Count); } diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifTagDescriptionAttributeTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifTagDescriptionAttributeTests.cs index d2198f9cae..1154b3439c 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifTagDescriptionAttributeTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifTagDescriptionAttributeTests.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Metadata.Profiles.Exif; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif; diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifValueTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifValueTests.cs index 548329250e..d04aa5e765 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifValueTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifValueTests.cs @@ -23,7 +23,9 @@ public class ExifValueTests { Assert.NotNull(this.profile); - return this.profile.GetValue(ExifTag.Software); + this.profile.TryGetValue(ExifTag.Software, out IExifValue value); + + return value; } [Fact] diff --git a/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs index 594eb7e7c8..21b92a01e8 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs @@ -4,6 +4,7 @@ using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.ImageSharp.Tests.TestUtilities; namespace SixLabors.ImageSharp.Tests.Processing.Transforms; diff --git a/tests/ImageSharp.Tests/TestUtilities/ExifProfileExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/ExifProfileExtensions.cs new file mode 100644 index 0000000000..259b6a9335 --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/ExifProfileExtensions.cs @@ -0,0 +1,18 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.Metadata.Profiles.Exif; + +namespace SixLabors.ImageSharp.Tests.TestUtilities; + +public static class ExifProfileExtensions +{ + public static IExifValue GetValue(this ExifProfile exifProfileInput, ExifTag tag, bool assertTrue = true) + { + bool boolValue = exifProfileInput.TryGetValue(tag, out IExifValue value); + + Assert.Equal(assertTrue, boolValue); + + return value; + } +} From 4949c348faaf1bc61ac764e4af7153703d383823 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Sat, 21 Jan 2023 13:20:14 +0100 Subject: [PATCH 05/37] Change CodePagesEncodingProvider to Encoding --- .../Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index bfe991f833..f743a2e24a 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -26,8 +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) ?? - throw new InvalidOperationException(); + private static Encoding JIS0208Encoding => Encoding.GetEncoding(20932); public static bool IsEncodedString(ExifTagValue tag) => tag switch { From ff54427090a62fc9c5b941c1dc7c1d96c2109a67 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Sat, 21 Jan 2023 13:44:53 +0100 Subject: [PATCH 06/37] Fix Encoding --- .../Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index f743a2e24a..e9f46731c8 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -26,7 +26,14 @@ 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 => Encoding.GetEncoding(20932); + private static Encoding JIS0208Encoding + { + get + { + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + return Encoding.GetEncoding(20932); + } + } public static bool IsEncodedString(ExifTagValue tag) => tag switch { From 8a291f61fe4a5fb614fb2071fa20efdaf335ffa6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sun, 22 Jan 2023 22:09:19 +1000 Subject: [PATCH 07/37] Add test + references --- .../Drawing/DrawImageTests.cs | 38 +++++++++++++++---- .../WorksWithDifferentBounds_10_10.png | 3 ++ .../WorksWithDifferentBounds_25_50.png | 3 ++ .../WorksWithDifferentBounds_50_25.png | 3 ++ .../WorksWithDifferentBounds_50_50.png | 3 ++ 5 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png create mode 100644 tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png create mode 100644 tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png create mode 100644 tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 0dcb961f84..60e8b4ccff 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -138,6 +138,33 @@ public class DrawImageTests appendSourceFileOrDescription: false); } + [Theory] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 10, 10)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 50, 25)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 25, 50)] + [WithSolidFilledImages(100, 100, "White", PixelTypes.Rgba32, 50, 50)] + public void WorksWithDifferentBounds(TestImageProvider provider, int width, int height) + { + using Image background = provider.GetImage(); + using Image overlay = new(50, 50); + Assert.True(overlay.DangerousTryGetSinglePixelMemory(out Memory overlayMem)); + overlayMem.Span.Fill(Color.Black); + + background.Mutate(c => c.DrawImage(overlay, new Rectangle(0, 0, width, height), PixelColorBlendingMode.Normal, 1F)); + + background.DebugSave( + provider, + testOutputDetails: $"{width}_{height}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + + background.CompareToReferenceOutput( + provider, + testOutputDetails: $"{width}_{height}", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + [Theory] [WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)] public void DrawTransformed(TestImageProvider provider) @@ -158,12 +185,12 @@ public class DrawImageTests Point position = new((image.Width - blend.Width) / 2, (image.Height - blend.Height) / 2); image.Mutate(x => x.DrawImage(blend, position, .75F)); - image.DebugSave(provider, appendSourceFileOrDescription: false, appendPixelTypeToFileName: false); + image.DebugSave(provider, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); image.CompareToReferenceOutput( ImageComparer.TolerantPercentage(0.002f), provider, - appendSourceFileOrDescription: false, - appendPixelTypeToFileName: false); + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } [Theory] @@ -179,9 +206,6 @@ public class DrawImageTests Assert.Contains("does not overlap", ex.ToString()); - void Test() - { - background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions())); - } + void Test() => background.Mutate(context => context.DrawImage(overlay, new Point(x, y), new GraphicsOptions())); } } diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png new file mode 100644 index 0000000000..64ce14d509 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_10_10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f353ee06664a6ff27c533af63cffb9eac4917103ba0b7fff9084fb4d2d42fed7 +size 155 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png new file mode 100644 index 0000000000..7e0466186a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_25_50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af198da8f611eb97f3e4e358cb097cd292771d52e991de76495f073c1f1b9338 +size 154 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png new file mode 100644 index 0000000000..6b93e597eb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35bda87f28e03c5ed0d45412e367fae9b04b7684f5242dc20e7709e8ed71cd86 +size 156 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png new file mode 100644 index 0000000000..540082dfdf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentBounds_50_50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8b9ff745592bb0e0a365cb0985a5519bf567fc73a09211c88bcda51356f9202 +size 155 From 6c2d6fa2fc2cab0b5b15f1bad6dbc04dfe60f6d5 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 23 Jan 2023 21:57:14 +1100 Subject: [PATCH 08/37] Update tests/ImageSharp.Tests/Drawing/DrawImageTests.cs Co-authored-by: Scott Williams --- tests/ImageSharp.Tests/Drawing/DrawImageTests.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 60e8b4ccff..33068e5442 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -146,9 +146,7 @@ public class DrawImageTests public void WorksWithDifferentBounds(TestImageProvider provider, int width, int height) { using Image background = provider.GetImage(); - using Image overlay = new(50, 50); - Assert.True(overlay.DangerousTryGetSinglePixelMemory(out Memory overlayMem)); - overlayMem.Span.Fill(Color.Black); + using Image overlay = new(50, 50, Color.Black.ToRgba32()); background.Mutate(c => c.DrawImage(overlay, new Rectangle(0, 0, width, height), PixelColorBlendingMode.Normal, 1F)); From 493ad9f5a47030ee5cd1ccb491f6711a9b4959b0 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 23 Jan 2023 21:11:08 +1000 Subject: [PATCH 09/37] Update intellisense docs. --- .../Extensions/Drawing/DrawImageExtensions.cs | 188 +++++++++--------- .../Drawing/DrawImageTests.cs | 6 +- 2 files changed, 96 insertions(+), 98 deletions(-) diff --git a/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs index eba107545d..ad93d6f167 100644 --- a/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Drawing/DrawImageExtensions.cs @@ -12,12 +12,12 @@ namespace SixLabors.ImageSharp.Processing; public static class DrawImageExtensions { /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -28,13 +28,13 @@ public static class DrawImageExtensions } /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The structure that specifies the portion of the image to draw. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The rectangle structure that specifies the portion of the image to draw. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -46,13 +46,13 @@ public static class DrawImageExtensions } /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The blending mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The color blending mode. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -61,14 +61,14 @@ public static class DrawImageExtensions => DrawImage(source, image, Point.Empty, colorBlending, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The structure that specifies the portion of the image to draw. - /// The blending mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The rectangle structure that specifies the portion of the image to draw. + /// The color blending mode. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -78,14 +78,14 @@ public static class DrawImageExtensions => DrawImage(source, image, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. + /// The current image processing context. + /// The image to draw on the currently processing image. /// The color blending mode. /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -95,15 +95,15 @@ public static class DrawImageExtensions => DrawImage(source, image, Point.Empty, colorBlending, alphaComposition, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The structure that specifies the portion of the image to draw. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The rectangle structure that specifies the portion of the image to draw. /// The color blending mode. /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -114,12 +114,12 @@ public static class DrawImageExtensions => DrawImage(source, image, Point.Empty, rectangle, colorBlending, alphaComposition, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. + /// The current image processing context. + /// The image to draw on the currently processing image. /// The options, including the blending type and blending amount. - /// The . + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -127,13 +127,13 @@ public static class DrawImageExtensions => DrawImage(source, image, Point.Empty, options); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The structure that specifies the portion of the image to draw. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The rectangle structure that specifies the portion of the image to draw. /// The options, including the blending type and blending amount. - /// The . + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -142,13 +142,13 @@ public static class DrawImageExtensions => DrawImage(source, image, Point.Empty, rectangle, options); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -160,14 +160,14 @@ public static class DrawImageExtensions } /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The structure that specifies the portion of the image to draw. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The rectangle structure that specifies the portion of the image to draw. + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -180,14 +180,14 @@ public static class DrawImageExtensions } /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. /// The color blending to apply. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -197,15 +197,15 @@ public static class DrawImageExtensions => DrawImage(source, image, location, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The structure that specifies the portion of the image to draw. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The rectangle structure that specifies the portion of the image to draw. /// The color blending to apply. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -216,13 +216,13 @@ public static class DrawImageExtensions => DrawImage(source, image, location, rectangle, colorBlending, source.GetGraphicsOptions().AlphaCompositionMode, opacity); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. /// The options containing the blend mode and opacity. - /// The . + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -231,14 +231,14 @@ public static class DrawImageExtensions => DrawImage(source, image, location, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The structure that specifies the portion of the image to draw. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The rectangle structure that specifies the portion of the image to draw. /// The options containing the blend mode and opacity. - /// The . + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -248,15 +248,15 @@ public static class DrawImageExtensions => DrawImage(source, image, location, rectangle, options.ColorBlendingMode, options.AlphaCompositionMode, options.BlendPercentage); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. /// The color blending to apply. /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, @@ -267,16 +267,16 @@ public static class DrawImageExtensions => source.ApplyProcessor(new DrawImageProcessor(image, location, colorBlending, alphaComposition, opacity)); /// - /// Draws the given image together with the current one by blending their pixels. + /// Draws the given image together with the currently processing image by blending their pixels. /// - /// The image this method extends. - /// The image to blend with the currently processing image. - /// The location to draw the blended image. - /// The structure that specifies the portion of the image to draw. + /// The current image processing context. + /// The image to draw on the currently processing image. + /// The location on the currenty processing image at which to draw. + /// The rectangle structure that specifies the portion of the image to draw. /// The color blending to apply. /// The alpha composition mode. - /// The opacity of the image to blend. Must be between 0 and 1. - /// The . + /// The opacity of the image to draw. Must be between 0 and 1. + /// The . public static IImageProcessingContext DrawImage( this IImageProcessingContext source, Image image, diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs index 33068e5442..d017e5ad42 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTests.cs @@ -119,9 +119,7 @@ public class DrawImageTests public void WorksWithDifferentLocations(TestImageProvider provider, int x, int y) { using Image background = provider.GetImage(); - using Image overlay = new(50, 50); - Assert.True(overlay.DangerousTryGetSinglePixelMemory(out Memory overlayMem)); - overlayMem.Span.Fill(Color.Black); + using Image overlay = new(50, 50, Color.Black.ToRgba32()); background.Mutate(c => c.DrawImage(overlay, new Point(x, y), PixelColorBlendingMode.Normal, 1F)); @@ -146,7 +144,7 @@ public class DrawImageTests public void WorksWithDifferentBounds(TestImageProvider provider, int width, int height) { using Image background = provider.GetImage(); - using Image overlay = new(50, 50, Color.Black.ToRgba32()); + using Image overlay = new(50, 50, Color.Black.ToRgba32()); background.Mutate(c => c.DrawImage(overlay, new Rectangle(0, 0, width, height), PixelColorBlendingMode.Normal, 1F)); From 3c2885e382e9c5057d4e059ca6da4bdadb01f8a8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 23 Jan 2023 23:13:53 +1000 Subject: [PATCH 10/37] Allow zero DPI and only throw at EOF when not enough data --- .../Jpeg/Components/Decoder/JFifMarker.cs | 22 ++++--------------- .../Components/Decoder/SpectralConverter.cs | 6 +++++ .../Decoder/SpectralConverter{TPixel}.cs | 6 +++++ .../Formats/Jpeg/JpegDecoderCore.cs | 12 ++++++++++ .../Formats/Jpg/JpegDecoderTests.cs | 11 ++++++++++ .../Formats/Jpg/SpectralJpegTests.cs | 2 ++ tests/ImageSharp.Tests/TestImages.cs | 1 + tests/Images/Input/Jpg/issues/issue-2315.jpg | 3 +++ 8 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 tests/Images/Input/Jpg/issues/issue-2315.jpg diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs index 42dcf7200a..e13b26f9a9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs @@ -26,16 +26,6 @@ internal readonly struct JFifMarker : IEquatable /// The vertical pixel density. private JFifMarker(byte majorVersion, byte minorVersion, byte densityUnits, short xDensity, short yDensity) { - if (xDensity <= 0) - { - JpegThrowHelper.ThrowInvalidImageContentException($"X-Density {xDensity} must be greater than 0."); - } - - if (yDensity <= 0) - { - JpegThrowHelper.ThrowInvalidImageContentException($"Y-Density {yDensity} must be greater than 0."); - } - this.MajorVersion = majorVersion; this.MinorVersion = minorVersion; @@ -64,12 +54,12 @@ internal readonly struct JFifMarker : IEquatable public PixelResolutionUnit DensityUnits { get; } /// - /// Gets the horizontal pixel density. Must not be zero. + /// Gets the horizontal pixel density. /// public short XDensity { get; } /// - /// Gets the vertical pixel density. Must not be zero. + /// Gets the vertical pixel density. /// public short YDensity { get; } @@ -88,12 +78,8 @@ internal readonly struct JFifMarker : IEquatable byte densityUnits = bytes[7]; short xDensity = (short)((bytes[8] << 8) | bytes[9]); short yDensity = (short)((bytes[10] << 8) | bytes[11]); - - if (xDensity > 0 && yDensity > 0) - { - marker = new JFifMarker(majorVersion, minorVersion, densityUnits, xDensity, yDensity); - return true; - } + marker = new JFifMarker(majorVersion, minorVersion, densityUnits, xDensity, yDensity); + return true; } marker = default; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs index 0eb484b94a..51d9bfbced 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs @@ -121,4 +121,10 @@ internal abstract class SpectralConverter return size; } + + /// + /// Gets a value indicating whether the converter has a pixel buffer. + /// + /// if the converter has a pixel buffer; otherwise, . + public abstract bool HasPixelBuffer(); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs index 4bb58d8a12..d6250127f5 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs @@ -85,6 +85,12 @@ internal class SpectralConverter : SpectralConverter, IDisposable /// public Configuration Configuration { get; } + /// + /// Gets a value indicating whether the converter has a pixel buffer. + /// + /// if the converter has a pixel buffer; otherwise, . + public override bool HasPixelBuffer() => this.pixelBuffer is not null; + /// /// Gets converted pixel buffer. /// diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 511ec1ba1d..51de9ffbd1 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -356,6 +356,18 @@ internal sealed class JpegDecoderCore : IRawJpegData, IImageDecoderInternals // to uint to avoid sign extension. if (stream.RemainingBytes < (uint)markerContentByteSize) { + if (metadataOnly && this.Metadata != null && this.Frame != null) + { + // We have enough data to decode the image, so we can stop parsing. + return; + } + + if (this.Metadata != null && this.Frame != null && spectralConverter.HasPixelBuffer()) + { + // We have enough data to decode the image, so we can stop parsing. + return; + } + JpegThrowHelper.ThrowNotEnoughBytesForMarker(fileMarker.Marker); } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 1d5a7e0ff8..425d12497c 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -300,4 +300,15 @@ public partial class JpegDecoderTests image.DebugSave(provider); image.CompareToOriginal(provider); } + + // https://github.com/SixLabors/ImageSharp/issues/2315 + [Theory] + [WithFile(TestImages.Jpeg.Issues.Issue2315_NotEnoughBytes, PixelTypes.Rgba32)] + public void Issue2315_DecodeWorks(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(JpegDecoder.Instance); + image.DebugSave(provider); + image.CompareToOriginal(provider); + } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs index 58347a0724..805ee586a8 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs @@ -187,6 +187,8 @@ public class SpectralJpegTests } } + public override bool HasPixelBuffer() => throw new NotImplementedException(); + public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) { this.frame = frame; diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 29223b1fe0..22a48ebee4 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -281,6 +281,7 @@ public static class TestImages public const string ValidExifArgumentNullExceptionOnEncode = "Jpg/issues/Issue2087-exif-null-reference-on-encode.jpg"; public const string Issue2133_DeduceColorSpace = "Jpg/issues/Issue2133.jpg"; public const string Issue2136_ScanMarkerExtraneousBytes = "Jpg/issues/Issue2136-scan-segment-extraneous-bytes.jpg"; + public const string Issue2315_NotEnoughBytes = "Jpg/issues/issue-2315.jpg"; public static class Fuzz { diff --git a/tests/Images/Input/Jpg/issues/issue-2315.jpg b/tests/Images/Input/Jpg/issues/issue-2315.jpg new file mode 100644 index 0000000000..fe3001eddc --- /dev/null +++ b/tests/Images/Input/Jpg/issues/issue-2315.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f129b057efb499d492e9afcffdd98de62aac1e04b97a09a75b4799ba498cd3c1 +size 319056 From c44cd6c244f4671fdb8b4c7fd426afc865e55084 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 23 Jan 2023 23:26:15 +1000 Subject: [PATCH 11/37] Update DecodeJpegParseStreamOnly.cs --- .../Codecs/Jpeg/DecodeJpegParseStreamOnly.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs index aa88242ce4..b5a7245292 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs @@ -54,6 +54,8 @@ public class DecodeJpegParseStreamOnly { } + public override bool HasPixelBuffer() => throw new NotImplementedException(); + public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) { } From b5c6c22c21a91287034b2b68431334fdba1eb296 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Mon, 23 Jan 2023 20:36:39 +0100 Subject: [PATCH 12/37] Changes from Review * Throw InvalidImageContentException * Change GetDesctiption to TryGetDescription * Do not throw when creating exifvalue and adding it to ifdValues --- src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs | 2 +- src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs | 3 +++ .../Exif/ExifTagDescriptionAttribute.cs | 18 ++++++++++++------ .../Metadata/Profiles/Exif/ExifWriter.cs | 6 ++++-- .../Exif/Values/ExifValue{TValueType}.cs | 6 +----- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index 87784d1cb4..8333dbf31c 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -793,7 +793,7 @@ internal class TiffDecoderCore : IImageDecoderInternals { if (!exifProfile.TryGetValue(ExifTag.ImageWidth, out IExifValue width)) { - TiffThrowHelper.ThrowImageFormatException("The TIFF image frame is missing the ImageWidth"); + TiffThrowHelper.ThrowInvalidImageContentException("The TIFF image frame is missing the ImageWidth"); } DebugGuard.MustBeLessThanOrEqualTo((ulong)width.Value, (ulong)int.MaxValue, nameof(ExifTag.ImageWidth)); diff --git a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs index 3957ccb02f..4a03bd44f6 100644 --- a/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs +++ b/src/ImageSharp/Formats/Tiff/TiffThrowHelper.cs @@ -10,6 +10,9 @@ internal static class TiffThrowHelper [DoesNotReturn] public static Exception ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage); + [DoesNotReturn] + public static Exception ThrowInvalidImageContentException(string errorMessage) => throw new InvalidImageContentException(errorMessage); + [DoesNotReturn] public static Exception NotSupportedDecompressor(string compressionType) => throw new NotSupportedException($"Not supported decoder compression method: {compressionType}"); diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs index da5214087f..7a520343af 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -25,17 +26,20 @@ internal sealed class ExifTagDescriptionAttribute : Attribute /// /// The tag. /// The value. + /// The description. /// - /// The . + /// True when description was found /// - public static string? GetDescription(ExifTag tag, object? value) + public static bool TryGetDescription(ExifTag tag, object? value, [NotNullWhen(true)] out string? description) { - var tagValue = (ExifTagValue)(ushort)tag; + ExifTagValue tagValue = (ExifTagValue)(ushort)tag; FieldInfo? field = typeof(ExifTagValue).GetField(tagValue.ToString(), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); + description = null; + if (field is null) { - return null; + return false; } foreach (CustomAttributeData customAttribute in field.CustomAttributes) @@ -44,10 +48,12 @@ internal sealed class ExifTagDescriptionAttribute : Attribute if (Equals(attributeValue, value)) { - return (string?)customAttribute.ConstructorArguments[1].Value; + description = (string?)customAttribute.ConstructorArguments[1].Value; + + return description is not null; } } - return null; + return false; } } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs index 26442b2c41..76fb2ff39a 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs @@ -179,9 +179,11 @@ internal sealed class ExifWriter } ExifValue? result = ExifValues.Create(offset); - Guard.NotNull(result); - ifdValues.Add(result); + if (result is not null) + { + ifdValues.Add(result); + } return result; } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs index 6442f26846..e7a2fa5e5d 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValue{TValueType}.cs @@ -48,9 +48,5 @@ internal abstract class ExifValue : ExifValue, IExifValue ExifTagDescriptionAttribute.TryGetDescription(this.Tag, this.Value, out string? description) ? description : this.StringValue; } From c224dece1765026ca0da5086af88e71ed1fb30fc Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 24 Jan 2023 08:57:39 +1000 Subject: [PATCH 13/37] Update JFifMarkerTests.cs --- tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs index 3890c20e93..3b7e20eb4e 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs @@ -46,15 +46,6 @@ public class JFifMarkerTests Assert.Equal(default, marker); } - [Fact] - public void MarkerIgnoresCorrectHeaderButInvalidDensities() - { - bool isJFif = JFifMarker.TryParse(this.bytes3, out JFifMarker marker); - - Assert.False(isJFif); - Assert.Equal(default, marker); - } - [Fact] public void MarkerEqualityIsCorrect() { From b41611ae6d43ff2e534ed0148169cdb13d6fd9e7 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Tue, 24 Jan 2023 08:00:38 +0100 Subject: [PATCH 14/37] Remove nullable disable from zlib #2231 --- .../Compression/Zlib/DeflateThrowHelper.cs | 10 +++++++++ src/ImageSharp/Compression/Zlib/Deflater.cs | 2 -- .../Compression/Zlib/DeflaterEngine.cs | 12 ++++------ .../Compression/Zlib/DeflaterHuffman.cs | 9 -------- .../Compression/Zlib/DeflaterOutputStream.cs | 3 --- .../Compression/Zlib/DeflaterPendingBuffer.cs | 2 -- .../Compression/Zlib/ZlibDeflateStream.cs | 3 --- .../Compression/Zlib/ZlibInflateStream.cs | 6 +++-- .../Diagnostics/MemoryDiagnostics.cs | 7 +++--- .../Decompressors/DeflateTiffCompression.cs | 22 ++++++++++--------- 10 files changed, 33 insertions(+), 43 deletions(-) diff --git a/src/ImageSharp/Compression/Zlib/DeflateThrowHelper.cs b/src/ImageSharp/Compression/Zlib/DeflateThrowHelper.cs index ba22d5d85e..30761328f3 100644 --- a/src/ImageSharp/Compression/Zlib/DeflateThrowHelper.cs +++ b/src/ImageSharp/Compression/Zlib/DeflateThrowHelper.cs @@ -1,23 +1,33 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Diagnostics.CodeAnalysis; + namespace SixLabors.ImageSharp.Compression.Zlib; internal static class DeflateThrowHelper { + [DoesNotReturn] public static void ThrowAlreadyFinished() => throw new InvalidOperationException("Finish() already called."); + [DoesNotReturn] public static void ThrowAlreadyClosed() => throw new InvalidOperationException("Deflator already closed."); + [DoesNotReturn] public static void ThrowUnknownCompression() => throw new InvalidOperationException("Unknown compression function."); + [DoesNotReturn] public static void ThrowNotProcessed() => throw new InvalidOperationException("Old input was not completely processed."); + [DoesNotReturn] public static void ThrowNull(string name) => throw new ArgumentNullException(name); + [DoesNotReturn] public static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name); + [DoesNotReturn] public static void ThrowHeapViolated() => throw new InvalidOperationException("Huffman heap invariant violated."); + [DoesNotReturn] public static void ThrowNoDeflate() => throw new ImageFormatException("Cannot deflate all input."); } diff --git a/src/ImageSharp/Compression/Zlib/Deflater.cs b/src/ImageSharp/Compression/Zlib/Deflater.cs index f001b8a67c..f642ec85a7 100644 --- a/src/ImageSharp/Compression/Zlib/Deflater.cs +++ b/src/ImageSharp/Compression/Zlib/Deflater.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory; @@ -285,7 +284,6 @@ internal sealed class Deflater : IDisposable 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 47bc43f52e..31fa0238bf 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterEngine.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Runtime.CompilerServices; @@ -87,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. @@ -222,7 +221,7 @@ internal sealed unsafe class DeflaterEngine : IDisposable /// 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) { @@ -362,6 +361,8 @@ internal sealed unsafe class DeflaterEngine : IDisposable more = this.inputEnd - this.inputOff; } + ArgumentNullException.ThrowIfNull(this.inputBuf); + Unsafe.CopyBlockUnaligned( ref this.window.Span[this.strstart + this.lookahead], ref this.inputBuf[this.inputOff], @@ -393,11 +394,6 @@ internal sealed unsafe class DeflaterEngine : IDisposable 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 8c67699085..dc11de4259 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterHuffman.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Runtime.CompilerServices; @@ -427,10 +426,6 @@ internal sealed unsafe class DeflaterHuffman : IDisposable this.blTree.Dispose(); this.distTree.Dispose(); - this.Pending = null; - this.literalTree = null; - this.blTree = null; - this.distTree = null; this.isDisposed = true; } } @@ -977,10 +972,6 @@ internal sealed unsafe class DeflaterHuffman : IDisposable 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 cea2fd2721..de818fd8f5 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterOutputStream.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using SixLabors.ImageSharp.Memory; @@ -137,8 +136,6 @@ internal sealed class DeflaterOutputStream : Stream 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 28febdc118..37e7404e40 100644 --- a/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs +++ b/src/ImageSharp/Compression/Zlib/DeflaterPendingBuffer.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Runtime.CompilerServices; @@ -180,7 +179,6 @@ internal sealed unsafe class DeflaterPendingBuffer : IDisposable { 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 00c4aed3b1..2e52f84d7b 100644 --- a/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs +++ b/src/ImageSharp/Compression/Zlib/ZlibDeflateStream.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Formats.Png; @@ -172,8 +171,6 @@ internal sealed class ZlibDeflateStream : Stream 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 f9e678605c..06a7c3928c 100644 --- a/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs +++ b/src/ImageSharp/Compression/Zlib/ZlibInflateStream.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable +using System.Diagnostics.CodeAnalysis; using System.IO.Compression; using SixLabors.ImageSharp.IO; @@ -90,7 +90,7 @@ internal sealed class ZlibInflateStream : Stream /// /// 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. @@ -98,6 +98,7 @@ internal sealed class ZlibInflateStream : Stream /// The current remaining data according to the chunk length. /// Whether the chunk to be inflated is a critical chunk. /// The . + [MemberNotNullWhen(true, nameof(CompressedStream))] public bool AllocateNewBytes(int bytes, bool isCriticalChunk) { this.currentDataRemaining = bytes; @@ -210,6 +211,7 @@ internal sealed class ZlibInflateStream : Stream this.isDisposed = true; } + [MemberNotNullWhen(true, nameof(CompressedStream))] private bool InitializeInflateStream(bool isCriticalChunk) { // Read the zlib header : http://tools.ietf.org/html/rfc1950 diff --git a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs index f00ee1b2a8..8327daf23b 100644 --- a/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs +++ b/src/ImageSharp/Diagnostics/MemoryDiagnostics.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable namespace SixLabors.ImageSharp.Diagnostics; @@ -17,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(); @@ -50,12 +49,12 @@ public static class MemoryDiagnostics /// /// 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/Tiff/Compression/Decompressors/DeflateTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs index 4c377c8783..27c311009c 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/DeflateTiffCompression.cs @@ -50,19 +50,21 @@ internal sealed class DeflateTiffCompression : TiffBaseDecompressor return left > 0 ? left : 0; })) { - deframeStream.AllocateNewBytes(byteCount, true); - DeflateStream dataStream = deframeStream.CompressedStream; - - int totalRead = 0; - while (totalRead < buffer.Length) + if (deframeStream.AllocateNewBytes(byteCount, true)) { - int bytesRead = dataStream.Read(buffer, totalRead, buffer.Length - totalRead); - if (bytesRead <= 0) + DeflateStream? dataStream = deframeStream.CompressedStream; + + int totalRead = 0; + while (totalRead < buffer.Length) { - break; - } + int bytesRead = dataStream.Read(buffer, totalRead, buffer.Length - totalRead); + if (bytesRead <= 0) + { + break; + } - totalRead += bytesRead; + totalRead += bytesRead; + } } } From 4605f664bcab81d7c9f4ee9badc2b58030f34d8c Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 10:50:06 +0100 Subject: [PATCH 15/37] Remove nullable disable from ColorSpace and Color #2231 --- src/ImageSharp/Color/Color.cs | 5 ++--- .../ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs | 6 ++++-- .../ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs | 2 +- .../ColorSpaces/Conversion/ColorSpaceConverter.cs | 4 ++-- .../ColorSpaces/Conversion/ColorSpaceConverterOptions.cs | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index 58bc77d14f..99a271bcf7 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -20,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) @@ -317,7 +316,7 @@ public readonly partial struct Color : IEquatable } /// - 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/Conversion/ColorSpaceConverter.Adapt.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs index 52a9ef27ee..c4ce0350a6 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs @@ -32,7 +32,8 @@ public partial class ColorSpaceConverter return color; } - return this.chromaticAdaptation.Transform(color, sourceWhitePoint, targetWhitePoint); + // We know that chromaticAdaption is not null because performChromaticAdaption is checked + return this.chromaticAdaptation!.Transform(color, sourceWhitePoint, targetWhitePoint); } /// @@ -132,7 +133,8 @@ public partial class ColorSpaceConverter CieXyz unadapted = converterToXYZ.Convert(color); // Adaptation - CieXyz adapted = this.chromaticAdaptation.Transform(unadapted, color.WorkingSpace.WhitePoint, this.targetRgbWorkingSpace.WhitePoint); + // We know that chromaticAdaption is not null because performChromaticAdaption is checked + 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 d7fa5f539a..52fa582356 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable +using System.Diagnostics.CodeAnalysis; using System.Numerics; namespace SixLabors.ImageSharp.ColorSpaces.Conversion; @@ -19,7 +19,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/ColorSpaceConverterOptions.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs index 4fb5210670..9f576de726 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverterOptions.cs @@ -44,7 +44,7 @@ public class ColorSpaceConverterOptions /// /// Gets or sets the chromatic adaptation method used. When null, no adaptation will be performed. /// - public IChromaticAdaptation ChromaticAdaptation { get; set; } = new VonKriesChromaticAdaptation(); + public IChromaticAdaptation? ChromaticAdaptation { get; set; } = new VonKriesChromaticAdaptation(); /// /// Gets or sets transformation matrix used in conversion to and from . From e70e71b16c665e98cb48f464fdc3ab37c614f916 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 10:57:29 +0100 Subject: [PATCH 16/37] Remove nullable disable from Memory.Allocators #2231 --- .../Memory/Allocators/Internals/Gen2GcCallback.cs | 11 +++++------ .../Allocators/Internals/ManagedBufferBase.cs | 2 +- .../Internals/RefCountedMemoryLifetimeGuard.cs | 3 +-- .../Internals/SharedArrayPoolBuffer{T}.cs | 6 ++---- .../Internals/UniformUnmanagedMemoryPool.cs | 7 +++---- .../Allocators/Internals/UnmanagedMemoryHandle.cs | 11 +++++------ .../UniformUnmanagedMemoryPoolMemoryAllocator.cs | 2 +- src/ImageSharp/Memory/Buffer2DExtensions.cs | 2 +- src/ImageSharp/Memory/Buffer2D{T}.cs | 4 ++-- .../DiscontiguousBuffers/MemoryGroupExtensions.cs | 2 +- .../DiscontiguousBuffers/MemoryGroupSpanCache.cs | 2 +- .../DiscontiguousBuffers/MemoryGroupView{T}.cs | 6 ++++-- .../MemoryGroup{T}.Consumed.cs | 2 +- .../DiscontiguousBuffers/MemoryGroup{T}.Owned.cs | 14 ++++++++------ .../Memory/DiscontiguousBuffers/MemoryGroup{T}.cs | 8 ++++---- 15 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs index 547f67d6a7..c0737a1140 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable // Port of BCL internal utility: // https://github.com/dotnet/runtime/blob/57bfe474518ab5b7cfe6bf7424a79ce3af9d6657/src/libraries/System.Private.CoreLib/src/System/Gen2GcCallback.cs @@ -15,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; @@ -32,7 +31,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject 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. @@ -43,7 +42,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject // Execute the callback method. try { - if (!this.callback1(targetObj)) + if (this.callback1 is not null && !this.callback1(targetObj)) { // If the callback returns false, this callback object is no longer needed. this.weakTargetObj.Free(); @@ -64,7 +63,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject // Execute the callback method. try { - if (!this.callback0()) + if (this.callback0 is not null && !this.callback0()) { // If the callback returns false, this callback object is no longer needed. return; diff --git a/src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs b/src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs index a18bd34474..be4cb8c8e4 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs @@ -43,5 +43,5 @@ internal abstract class ManagedBufferBase : MemoryManager /// Gets the object that should be pinned. /// /// The pinnable . - protected abstract object GetPinnableObject(); + protected abstract object? GetPinnableObject(); } diff --git a/src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs b/src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs index aed5d03e4b..4a202a96c3 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/RefCountedMemoryLifetimeGuard.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using SixLabors.ImageSharp.Diagnostics; @@ -15,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 166992266c..1d73b2ddf2 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Diagnostics; @@ -22,7 +21,7 @@ internal class SharedArrayPoolBuffer : ManagedBufferBase, IRefCounted this.lifetimeGuard = new LifetimeGuard(this.Array); } - public byte[] Array { get; private set; } + public byte[]? Array { get; private set; } protected override void Dispose(bool disposing) { @@ -41,7 +40,7 @@ internal class SharedArrayPoolBuffer : ManagedBufferBase, IRefCounted return MemoryMarshal.Cast(this.Array.AsSpan(0, this.lengthInBytes)); } - protected override object GetPinnableObject() => this.Array; + protected override object? GetPinnableObject() => this.Array; public void AddRef() { @@ -74,7 +73,6 @@ internal class SharedArrayPoolBuffer : ManagedBufferBase, IRefCounted // 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); - this.array = null; } } } diff --git a/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs b/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs index 464bc21650..aa8bcd3859 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/UniformUnmanagedMemoryPool.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Diagnostics; @@ -13,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(); @@ -97,7 +96,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx /// /// Rent buffers or return 'null' if the pool is full. /// - public UnmanagedMemoryHandle[] Rent(int bufferCount) + public UnmanagedMemoryHandle[]? Rent(int bufferCount) { UnmanagedMemoryHandle[] buffersLocal = this.buffers; @@ -248,7 +247,7 @@ internal partial class UniformUnmanagedMemoryPool : System.Runtime.ConstrainedEx 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 a6da445b65..c13fa754e2 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/UnmanagedMemoryHandle.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Runtime.InteropServices; @@ -20,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; @@ -114,9 +113,9 @@ internal struct UnmanagedMemoryHandle : IEquatable 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; @@ -124,7 +123,7 @@ internal struct UnmanagedMemoryHandle : IEquatable 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..2cb4421d5e 100644 --- a/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs +++ b/src/ImageSharp/Memory/Allocators/UniformUnmanagedMemoryPoolMemoryAllocator.cs @@ -135,7 +135,7 @@ internal sealed class UniformUnmanagedMemoryPoolMemoryAllocator : MemoryAllocato } // 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; } diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index 2eb05ea935..e7ac64eda0 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -22,7 +22,7 @@ public static class Buffer2DExtensions where T : struct { Guard.NotNull(buffer, nameof(buffer)); - return buffer.FastMemoryGroup.View; + return buffer.FastMemoryGroup.View!; } /// diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index 8d6465389f..a7957a9871 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -43,7 +43,7 @@ public sealed class Buffer2D : IDisposable /// 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 @@ public sealed class Buffer2D : IDisposable { 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); } /// diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs index 4656e6ef95..b4b1ffc6f4 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs @@ -106,7 +106,7 @@ internal static class MemoryGroupExtensions } } - internal static void CopyTo(this IMemoryGroup source, IMemoryGroup target) + internal static void CopyTo(this IMemoryGroup? source, IMemoryGroup? target) where T : struct { Guard.NotNull(source, nameof(source)); diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs index 36abfba886..dd3e67c371 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupSpanCache.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Memory; internal unsafe struct MemoryGroupSpanCache { public SpanCacheMode Mode; - public byte[] SingleArray; + public byte[]? SingleArray; public void* SinglePointer; public void*[] MultiPointer; diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs index 54e347e463..76371e6744 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupView{T}.cs @@ -1,9 +1,9 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Memory; @@ -21,7 +21,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) @@ -63,6 +63,7 @@ internal class MemoryGroupView : IMemoryGroup } } + [MemberNotNullWhen(true, nameof(owner))] public bool IsValid => this.owner != null; public Memory this[int index] @@ -99,6 +100,7 @@ internal class MemoryGroupView : IMemoryGroup this.owner = null; } + [MemberNotNull(nameof(owner))] private void EnsureIsValid() { if (!this.IsValid) 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 @@ internal abstract partial class MemoryGroup 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 e5bc91c983..664c137c13 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs @@ -1,8 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Memory.Internals; @@ -15,8 +15,8 @@ internal abstract partial class MemoryGroup /// public sealed class Owned : MemoryGroup, IEnumerable> { - private IMemoryOwner[] memoryOwners; - private RefCountedMemoryLifetimeGuard groupLifetimeGuard; + private IMemoryOwner[]? memoryOwners; + private RefCountedMemoryLifetimeGuard? groupLifetimeGuard; public Owned(IMemoryOwner[] memoryOwners, int bufferLength, long totalLength, bool swappable) : base(bufferLength, totalLength) @@ -123,7 +123,7 @@ internal abstract partial class MemoryGroup public override void RecreateViewAfterSwap() { - this.View.Invalidate(); + this.View?.Invalidate(); this.View = new MemoryGroupView(this); } @@ -141,7 +141,7 @@ internal abstract partial class MemoryGroup return; } - this.View.Invalidate(); + this.View?.Invalidate(); if (this.groupLifetimeGuard != null) { @@ -149,7 +149,7 @@ internal abstract partial class MemoryGroup } else { - foreach (IMemoryOwner memoryOwner in this.memoryOwners) + foreach (IMemoryOwner memoryOwner in this.memoryOwners!) { memoryOwner.Dispose(); } @@ -161,6 +161,7 @@ internal abstract partial class MemoryGroup } [MethodImpl(InliningOptions.ShortMethod)] + [MemberNotNull(nameof(memoryOwners))] private void EnsureNotDisposed() { if (this.memoryOwners is null) @@ -170,6 +171,7 @@ internal abstract partial class MemoryGroup } [MethodImpl(MethodImplOptions.NoInlining)] + [DoesNotReturn] private static void ThrowObjectDisposedException() => throw new ObjectDisposedException(nameof(MemoryGroup)); // When the MemoryGroup points to multiple buffers via `groupLifetimeGuard`, diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs index 1ef30e354c..237cbad7a7 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs @@ -1,9 +1,9 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using SixLabors.ImageSharp.Memory.Internals; @@ -41,7 +41,7 @@ internal abstract partial class MemoryGroup : IMemoryGroup, IDisposable /// 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; } @@ -150,7 +150,7 @@ internal abstract partial class MemoryGroup : IMemoryGroup, IDisposable long totalLengthInElements, int bufferAlignmentInElements, AllocationOptions options, - out MemoryGroup memoryGroup) + [NotNullWhen(true)] out MemoryGroup? memoryGroup) { Guard.NotNull(pool, nameof(pool)); Guard.MustBeGreaterThanOrEqualTo(totalLengthInElements, 0, nameof(totalLengthInElements)); @@ -188,7 +188,7 @@ internal abstract partial class MemoryGroup : IMemoryGroup, IDisposable bufferCount++; } - UnmanagedMemoryHandle[] arrays = pool.Rent(bufferCount); + UnmanagedMemoryHandle[]? arrays = pool.Rent(bufferCount); if (arrays == null) { From dfde8d8bf521681b8638980253f0c4ae5b88bb4f Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 17:11:25 +0100 Subject: [PATCH 17/37] Resolve PR comments --- .../Memory/Allocators/Internals/Gen2GcCallback.cs | 4 ++-- .../Memory/Allocators/Internals/ManagedBufferBase.cs | 2 +- .../Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs | 6 +++++- src/ImageSharp/Memory/Buffer2D{T}.cs | 2 +- .../Memory/DiscontiguousBuffers/MemoryGroup{T}.cs | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs index c0737a1140..6f48c56696 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/Gen2GcCallback.cs @@ -42,7 +42,7 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject // Execute the callback method. try { - if (this.callback1 is not null && !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 @@ internal sealed class Gen2GcCallback : CriticalFinalizerObject // Execute the callback method. try { - if (this.callback0 is not null && !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/ManagedBufferBase.cs b/src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs index be4cb8c8e4..a18bd34474 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs @@ -43,5 +43,5 @@ internal abstract class ManagedBufferBase : MemoryManager /// Gets the object that should be pinned. /// /// The pinnable . - protected abstract object? GetPinnableObject(); + protected abstract object GetPinnableObject(); } diff --git a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs index 1d73b2ddf2..4952c6b5e4 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs @@ -40,7 +40,11 @@ internal class SharedArrayPoolBuffer : ManagedBufferBase, IRefCounted return MemoryMarshal.Cast(this.Array.AsSpan(0, this.lengthInBytes)); } - protected override object? GetPinnableObject() => this.Array; + protected override object GetPinnableObject() + { + Guard.NotNull(this.Array); + return this.Array; + } public void AddRef() { diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index a7957a9871..8c9093a35b 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -43,7 +43,7 @@ public sealed class Buffer2D : IDisposable /// Gets the backing . /// /// The MemoryGroup. - public IMemoryGroup? MemoryGroup => this.FastMemoryGroup.View; + public IMemoryGroup MemoryGroup => this.FastMemoryGroup.View; /// /// Gets the backing without the view abstraction. diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs index 237cbad7a7..d63fd2076c 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.cs @@ -41,7 +41,7 @@ internal abstract partial class MemoryGroup : IMemoryGroup, IDisposable /// public bool IsValid { get; private set; } = true; - public MemoryGroupView? View { get; private set; } + public MemoryGroupView View { get; private set; } = null!; /// public abstract Memory this[int index] { get; } From 12cf563c5c54dd6feca7d3acaa0c72d994ae65d1 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 17:15:42 +0100 Subject: [PATCH 18/37] Use CheckDisposed --- .../Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs index 4952c6b5e4..609bb34a56 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -42,7 +43,7 @@ internal class SharedArrayPoolBuffer : ManagedBufferBase, IRefCounted protected override object GetPinnableObject() { - Guard.NotNull(this.Array); + this.CheckDisposed(); return this.Array; } @@ -55,6 +56,7 @@ internal class SharedArrayPoolBuffer : ManagedBufferBase, IRefCounted public void ReleaseRef() => this.lifetimeGuard.ReleaseRef(); [Conditional("DEBUG")] + [MemberNotNull(nameof(Array))] private void CheckDisposed() { if (this.Array == null) From 4efd49295a227ac57509db045774c07ee4283825 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 17:56:21 +0100 Subject: [PATCH 19/37] Resolve PR issues --- .../Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs | 5 +++-- .../Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs index 609bb34a56..f9434ee941 100644 --- a/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs +++ b/src/ImageSharp/Memory/Allocators/Internals/SharedArrayPoolBuffer{T}.cs @@ -67,7 +67,7 @@ internal class SharedArrayPoolBuffer : ManagedBufferBase, IRefCounted private sealed class LifetimeGuard : RefCountedMemoryLifetimeGuard { - private byte[] array; + private byte[]? array; public LifetimeGuard(byte[] array) => this.array = array; @@ -78,7 +78,8 @@ internal class SharedArrayPoolBuffer : ManagedBufferBase, IRefCounted // 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/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs index 03a2fb78f7..950e2a019e 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Consumed.cs @@ -48,6 +48,6 @@ internal abstract partial class MemoryGroup return ((IList>)this.source).GetEnumerator(); } - public override void Dispose() => this.View?.Invalidate(); + public override void Dispose() => this.View.Invalidate(); } } From 12421030c2846ceee2e886f397b9c84d7bc9cb1a Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 19:42:05 +0100 Subject: [PATCH 20/37] Update src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs Co-authored-by: Anton Firszov --- .../Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs index 664c137c13..eab90ee5a7 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs @@ -123,7 +123,7 @@ internal abstract partial class MemoryGroup public override void RecreateViewAfterSwap() { - this.View?.Invalidate(); + this.View.Invalidate(); this.View = new MemoryGroupView(this); } From 8f18e3596089a237d7a9bf59cbb9997b4219af5a Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 19:42:13 +0100 Subject: [PATCH 21/37] Update src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs Co-authored-by: Anton Firszov --- .../Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs index eab90ee5a7..9da0139e6e 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroup{T}.Owned.cs @@ -141,7 +141,7 @@ internal abstract partial class MemoryGroup return; } - this.View?.Invalidate(); + this.View.Invalidate(); if (this.groupLifetimeGuard != null) { From 6e70477cf2e477c1fbc981a1a31e68c6ff9399e2 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 19:42:21 +0100 Subject: [PATCH 22/37] Update src/ImageSharp/Memory/Buffer2D{T}.cs Co-authored-by: Anton Firszov --- src/ImageSharp/Memory/Buffer2D{T}.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index 8c9093a35b..8d6465389f 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -138,7 +138,7 @@ public sealed class Buffer2D : IDisposable { 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); } /// From 9c3d68f1f55f87d44822f91a98e053847218e674 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 25 Jan 2023 19:42:28 +0100 Subject: [PATCH 23/37] Update src/ImageSharp/Memory/Buffer2DExtensions.cs Co-authored-by: Anton Firszov --- src/ImageSharp/Memory/Buffer2DExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs index e7ac64eda0..2eb05ea935 100644 --- a/src/ImageSharp/Memory/Buffer2DExtensions.cs +++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs @@ -22,7 +22,7 @@ public static class Buffer2DExtensions where T : struct { Guard.NotNull(buffer, nameof(buffer)); - return buffer.FastMemoryGroup.View!; + return buffer.FastMemoryGroup.View; } /// From 54df7ab641df05975e895036259d49f85703607b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 26 Jan 2023 15:23:35 +1000 Subject: [PATCH 24/37] Safer cast, cleanup and comment --- .../Metadata/Profiles/Exif/ExifProfile.cs | 18 +++++++++--------- .../Metadata/Profiles/Exif/ExifReader.cs | 1 + .../Metadata/Profiles/Exif/ExifWriter.cs | 5 ++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs index e14c88229d..dd5792ae79 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs @@ -2,7 +2,6 @@ // Licensed under the Six Labors Split License. using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Metadata.Profiles.Exif; @@ -79,7 +78,7 @@ public sealed class ExifProfile : IDeepCloneable this.InvalidTags = other.InvalidTags.Count > 0 ? new List(other.InvalidTags) - : (IReadOnlyList)Array.Empty(); + : Array.Empty(); if (other.values != null) { @@ -161,7 +160,7 @@ public sealed class ExifProfile : IDeepCloneable return false; } - using (var memStream = new MemoryStream(this.data, this.thumbnailOffset, this.thumbnailLength)) + using (MemoryStream memStream = new(this.data, this.thumbnailOffset, this.thumbnailLength)) { image = Image.Load(memStream); return true; @@ -237,12 +236,12 @@ public sealed class ExifProfile : IDeepCloneable return Array.Empty(); } - var writer = new ExifWriter(this.values, this.Parts); + ExifWriter writer = new(this.values, this.Parts); return writer.GetData(); } /// - public ExifProfile DeepClone() => new ExifProfile(this); + public ExifProfile DeepClone() => new(this); /// /// Returns the value with the specified tag. @@ -267,6 +266,7 @@ public sealed class ExifProfile : IDeepCloneable /// /// The tag of the exif value. /// The value. + /// Newly created value is null. internal void SetValueInternal(ExifTag tag, object? value) { foreach (IExifValue exifValue in this.Values) @@ -281,7 +281,7 @@ public sealed class ExifProfile : IDeepCloneable ExifValue? newExifValue = ExifValues.Create(tag); if (newExifValue is null) { - throw new NotSupportedException(); + throw new NotSupportedException($"Newly created value for tag {tag} is null."); } newExifValue.TrySetValue(value); @@ -310,7 +310,7 @@ public sealed class ExifProfile : IDeepCloneable this.RemoveValue(value.Tag); } - var newResolution = new Rational(resolution, false); + Rational newResolution = new(resolution, false); this.SetValue(tag, newResolution); } @@ -328,13 +328,13 @@ public sealed class ExifProfile : IDeepCloneable return; } - var reader = new ExifReader(this.data); + ExifReader reader = new(this.data); this.values = reader.ReadValues(); this.InvalidTags = reader.InvalidTags.Count > 0 ? new List(reader.InvalidTags) - : (IReadOnlyList)Array.Empty(); + : Array.Empty(); this.thumbnailOffset = (int)reader.ThumbnailOffset; this.thumbnailLength = (int)reader.ThumbnailLength; diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs index 7b989c8d8a..885db3a5e9 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs @@ -22,6 +22,7 @@ internal class ExifReader : BaseExifReader public ExifReader(byte[] exifData, MemoryAllocator? allocator) : base(new MemoryStream(exifData ?? throw new ArgumentNullException(nameof(exifData))), allocator) { + // TODO: We never call this constructor passing a non-null allocator. } /// diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs index 76fb2ff39a..1d2dca8700 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs @@ -90,7 +90,7 @@ internal sealed class ExifWriter if (gpsLength > 0) { i = this.WriteHeaders(this.gpsValues, result, i); - i = this.WriteData(startIndex, this.gpsValues, result, i); + this.WriteData(startIndex, this.gpsValues, result, i); } return result; @@ -228,9 +228,8 @@ internal sealed class ExifWriter return false; } - if (exifValue.DataType == ExifDataType.Ascii) + if (exifValue.DataType == ExifDataType.Ascii && value is string stringValue) { - string stringValue = (string)value; return stringValue.Length > 0; } From 7f1fc960ed26d392f212d7b8ab43dd043fe37bac Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 26 Jan 2023 16:55:03 +1000 Subject: [PATCH 25/37] Use cache to make type threadsafe --- .../Conversion/ColorSpaceConverter.Adapt.cs | 2 +- .../Conversion/ColorSpaceConverter.CieXyz.cs | 18 +++++------------- .../Conversion/ColorSpaceConverter.cs | 3 +-- .../WorkingSpaces/RgbWorkingSpace.cs | 4 +--- 4 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs index c4ce0350a6..b4934e44ac 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Adapt.cs @@ -129,7 +129,7 @@ public partial class ColorSpaceConverter } // Conversion to XYZ - LinearRgbToCieXyzConverter converterToXYZ = this.GetLinearRgbToCieXyzConverter(color.WorkingSpace); + LinearRgbToCieXyzConverter converterToXYZ = GetLinearRgbToCieXyzConverter(color.WorkingSpace); CieXyz unadapted = converterToXYZ.Convert(color); // Adaptation diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs index 65298597c3..1244655227 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.CieXyz.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. +using System.Collections.Concurrent; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -11,9 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion; /// public partial class ColorSpaceConverter { - private static readonly HunterLabToCieXyzConverter HunterLabToCieXyzConverter = new(); - - private LinearRgbToCieXyzConverter? linearRgbToCieXyzConverter; + private static readonly ConcurrentDictionary ConverterCache = new(); /// /// Converts a into a . @@ -327,7 +326,7 @@ public partial class ColorSpaceConverter public CieXyz ToCieXyz(in LinearRgb color) { // Conversion - LinearRgbToCieXyzConverter converter = this.GetLinearRgbToCieXyzConverter(color.WorkingSpace); + LinearRgbToCieXyzConverter converter = GetLinearRgbToCieXyzConverter(color.WorkingSpace); CieXyz unadapted = converter.Convert(color); return this.Adapt(unadapted, color.WorkingSpace.WhitePoint); @@ -454,13 +453,6 @@ public partial class ColorSpaceConverter /// /// The source working space /// The - private LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace) - { - if (this.linearRgbToCieXyzConverter?.SourceWorkingSpace.Equals(workingSpace) == true) - { - return this.linearRgbToCieXyzConverter; - } - - return this.linearRgbToCieXyzConverter = new LinearRgbToCieXyzConverter(workingSpace); - } + private static LinearRgbToCieXyzConverter GetLinearRgbToCieXyzConverter(RgbWorkingSpace workingSpace) + => ConverterCache.GetOrAdd(workingSpace, (key) => new LinearRgbToCieXyzConverter(key)); } diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs index 52fa582356..b5e3162e64 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using System.Diagnostics.CodeAnalysis; using System.Numerics; namespace SixLabors.ImageSharp.ColorSpaces.Conversion; @@ -12,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion; public partial class ColorSpaceConverter { // Options. - private static readonly ColorSpaceConverterOptions DefaultOptions = new ColorSpaceConverterOptions(); + private static readonly ColorSpaceConverterOptions DefaultOptions = new(); private readonly Matrix4x4 lmsAdaptationMatrix; private readonly CieXyz whitePoint; private readonly CieXyz targetLuvWhitePoint; diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs index f22f2ff1fa..dd1dc62a86 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpace.cs @@ -75,7 +75,5 @@ public abstract class RgbWorkingSpace /// public override int GetHashCode() - { - return HashCode.Combine(this.WhitePoint, this.ChromaticityCoordinates); - } + => HashCode.Combine(this.WhitePoint, this.ChromaticityCoordinates); } From e9a693b99aafb03a39e89f860a3ed55e64c18c2b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 26 Jan 2023 18:08:53 +1000 Subject: [PATCH 26/37] Normalize parameters across all extension methods --- .../Processing/AdaptiveThresholdExtensions.cs | 24 +++---- .../Binarization/BinaryDitherExtensions.cs | 16 ++--- .../Binarization/BinaryThresholdExtensions.cs | 32 +++++----- .../Convolution/BokehBlurExtensions.cs | 16 ++--- .../Convolution/BoxBlurExtensions.cs | 18 +++--- .../Convolution/DetectEdgesExtensions.cs | 56 ++++++++--------- .../Convolution/GaussianBlurExtensions.cs | 18 +++--- .../Convolution/GaussianSharpenExtensions.cs | 18 +++--- .../Convolution/MedianBlurExtensions.cs | 10 +-- .../Extensions/Dithering/DitherExtensions.cs | 40 ++++++------ .../Extensions/Effects/OilPaintExtensions.cs | 18 +++--- .../Effects/PixelRowDelegateExtensions.cs | 32 +++++----- .../Extensions/Effects/PixelateExtensions.cs | 12 ++-- .../Filters/BlackWhiteExtensions.cs | 10 +-- .../Filters/BrightnessExtensions.cs | 10 +-- .../Filters/ColorBlindnessExtensions.cs | 10 +-- .../Extensions/Filters/ContrastExtensions.cs | 10 +-- .../Extensions/Filters/FilterExtensions.cs | 10 +-- .../Extensions/Filters/GrayscaleExtensions.cs | 16 ++--- .../Extensions/Filters/HueExtensions.cs | 10 +-- .../Extensions/Filters/InvertExtensions.cs | 10 +-- .../Filters/KodachromeExtensions.cs | 10 +-- .../Extensions/Filters/LightnessExtensions.cs | 8 +-- .../Extensions/Filters/LomographExtensions.cs | 8 +-- .../Extensions/Filters/OpacityExtensions.cs | 10 +-- .../Extensions/Filters/PolaroidExtensions.cs | 8 +-- .../Extensions/Filters/SaturateExtensions.cs | 10 +-- .../Extensions/Filters/SepiaExtensions.cs | 18 +++--- .../HistogramEqualizationExtensions.cs | 10 +-- .../Overlays/BackgroundColorExtensions.cs | 16 ++--- .../Extensions/Overlays/GlowExtensions.cs | 48 +++++++------- .../Extensions/Overlays/VignetteExtensions.cs | 40 ++++++------ .../Quantization/QuantizeExtensions.cs | 16 ++--- .../Transforms/AutoOrientExtensions.cs | 6 +- .../Extensions/Transforms/CropExtensions.cs | 10 +-- .../Transforms/EntropyCropExtensions.cs | 8 +-- .../Extensions/Transforms/FlipExtensions.cs | 6 +- .../Extensions/Transforms/PadExtensions.cs | 8 +-- .../Extensions/Transforms/ResizeExtensions.cs | 40 ++++++------ .../Extensions/Transforms/RotateExtensions.cs | 14 ++--- .../Transforms/RotateFlipExtensions.cs | 6 +- .../Extensions/Transforms/SkewExtensions.cs | 10 +-- .../Transforms/SwizzleExtensions.cs | 4 +- .../Transforms/TransformExtensions.cs | 62 +++++++++---------- 44 files changed, 384 insertions(+), 388 deletions(-) diff --git a/src/ImageSharp/Processing/AdaptiveThresholdExtensions.cs b/src/ImageSharp/Processing/AdaptiveThresholdExtensions.cs index fce2f574db..d008d1f67e 100644 --- a/src/ImageSharp/Processing/AdaptiveThresholdExtensions.cs +++ b/src/ImageSharp/Processing/AdaptiveThresholdExtensions.cs @@ -13,61 +13,61 @@ public static class AdaptiveThresholdExtensions /// /// Applies Bradley Adaptive Threshold to the image. /// - /// The image this method extends. - /// The . + /// The current image processing context. + /// The . public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source) => source.ApplyProcessor(new AdaptiveThresholdProcessor()); /// /// Applies Bradley Adaptive Threshold to the image. /// - /// The image this method extends. + /// The current image processing context. /// Threshold limit (0.0-1.0) to consider for binarization. - /// The . + /// The . public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, float thresholdLimit) => source.ApplyProcessor(new AdaptiveThresholdProcessor(thresholdLimit)); /// /// Applies Bradley Adaptive Threshold to the image. /// - /// The image this method extends. + /// The current image processing context. /// Upper (white) color for thresholding. /// Lower (black) color for thresholding. - /// The . + /// The . public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, Color upper, Color lower) => source.ApplyProcessor(new AdaptiveThresholdProcessor(upper, lower)); /// /// Applies Bradley Adaptive Threshold to the image. /// - /// The image this method extends. + /// The current image processing context. /// Upper (white) color for thresholding. /// Lower (black) color for thresholding. /// Threshold limit (0.0-1.0) to consider for binarization. - /// The . + /// The . public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, Color upper, Color lower, float thresholdLimit) => source.ApplyProcessor(new AdaptiveThresholdProcessor(upper, lower, thresholdLimit)); /// /// Applies Bradley Adaptive Threshold to the image. /// - /// The image this method extends. + /// The current image processing context. /// Upper (white) color for thresholding. /// Lower (black) color for thresholding. /// Rectangle region to apply the processor on. - /// The . + /// The . public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, Color upper, Color lower, Rectangle rectangle) => source.ApplyProcessor(new AdaptiveThresholdProcessor(upper, lower), rectangle); /// /// Applies Bradley Adaptive Threshold to the image. /// - /// The image this method extends. + /// The current image processing context. /// Upper (white) color for thresholding. /// Lower (black) color for thresholding. /// Threshold limit (0.0-1.0) to consider for binarization. /// Rectangle region to apply the processor on. - /// The . + /// The . public static IImageProcessingContext AdaptiveThreshold(this IImageProcessingContext source, Color upper, Color lower, float thresholdLimit, Rectangle rectangle) => source.ApplyProcessor(new AdaptiveThresholdProcessor(upper, lower, thresholdLimit), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Binarization/BinaryDitherExtensions.cs b/src/ImageSharp/Processing/Extensions/Binarization/BinaryDitherExtensions.cs index 887455b821..e490cdf85f 100644 --- a/src/ImageSharp/Processing/Extensions/Binarization/BinaryDitherExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Binarization/BinaryDitherExtensions.cs @@ -14,9 +14,9 @@ public static class BinaryDitherExtensions /// /// Dithers the image reducing it to two colors using ordered dithering. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryDither(this IImageProcessingContext source, IDither dither) => BinaryDither(source, dither, Color.White, Color.Black); @@ -24,11 +24,11 @@ public static class BinaryDitherExtensions /// /// Dithers the image reducing it to two colors using ordered dithering. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryDither( this IImageProcessingContext source, IDither dither, @@ -39,12 +39,12 @@ public static class BinaryDitherExtensions /// /// Dithers the image reducing it to two colors using ordered dithering. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryDither( this IImageProcessingContext source, IDither dither, @@ -54,14 +54,14 @@ public static class BinaryDitherExtensions /// /// Dithers the image reducing it to two colors using ordered dithering. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryDither( this IImageProcessingContext source, IDither dither, diff --git a/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs b/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs index 802ad06d75..815b059cf5 100644 --- a/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs @@ -15,19 +15,19 @@ public static class BinaryThresholdExtensions /// Applies binarization to the image splitting the pixels at the given threshold with /// Luminance as the color component to be compared to threshold. /// - /// The image this method extends. + /// The current image processing context. /// The threshold to apply binarization of the image. Must be between 0 and 1. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold) => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdMode.Luminance)); /// /// Applies binarization to the image splitting the pixels at the given threshold. /// - /// The image this method extends. + /// The current image processing context. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// Selects the value to be compared to threshold. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, @@ -38,12 +38,12 @@ public static class BinaryThresholdExtensions /// Applies binarization to the image splitting the pixels at the given threshold with /// Luminance as the color component to be compared to threshold. /// - /// The image this method extends. + /// The current image processing context. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, @@ -53,13 +53,13 @@ public static class BinaryThresholdExtensions /// /// Applies binarization to the image splitting the pixels at the given threshold. /// - /// The image this method extends. + /// The current image processing context. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// Selects the value to be compared to threshold. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, @@ -71,11 +71,11 @@ public static class BinaryThresholdExtensions /// Applies binarization to the image splitting the pixels at the given threshold with /// Luminance as the color component to be compared to threshold. /// - /// The image this method extends. + /// The current image processing context. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, @@ -86,12 +86,12 @@ public static class BinaryThresholdExtensions /// /// Applies binarization to the image splitting the pixels at the given threshold. /// - /// The image this method extends. + /// The current image processing context. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold /// Selects the value to be compared to threshold. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, @@ -104,14 +104,14 @@ public static class BinaryThresholdExtensions /// Applies binarization to the image splitting the pixels at the given threshold with /// Luminance as the color component to be compared to threshold. /// - /// The image this method extends. + /// The current image processing context. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, @@ -123,7 +123,7 @@ public static class BinaryThresholdExtensions /// /// Applies binarization to the image splitting the pixels at the given threshold. /// - /// The image this method extends. + /// The current image processing context. /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold @@ -131,7 +131,7 @@ public static class BinaryThresholdExtensions /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, diff --git a/src/ImageSharp/Processing/Extensions/Convolution/BokehBlurExtensions.cs b/src/ImageSharp/Processing/Extensions/Convolution/BokehBlurExtensions.cs index 1688e5cc76..e3e6f13ed6 100644 --- a/src/ImageSharp/Processing/Extensions/Convolution/BokehBlurExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Convolution/BokehBlurExtensions.cs @@ -13,44 +13,44 @@ public static class BokehBlurExtensions /// /// Applies a bokeh blur to the image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext BokehBlur(this IImageProcessingContext source) => source.ApplyProcessor(new BokehBlurProcessor()); /// /// Applies a bokeh blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'radius' value representing the size of the area to sample. /// The 'components' value representing the number of kernels to use to approximate the bokeh effect. /// The gamma highlight factor to use to emphasize bright spots in the source image - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, int radius, int components, float gamma) => source.ApplyProcessor(new BokehBlurProcessor(radius, components, gamma)); /// /// Applies a bokeh blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new BokehBlurProcessor(), rectangle); /// /// Applies a bokeh blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'radius' value representing the size of the area to sample. /// The 'components' value representing the number of kernels to use to approximate the bokeh effect. /// The gamma highlight factor to use to emphasize bright spots in the source image /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, int radius, int components, float gamma, Rectangle rectangle) => source.ApplyProcessor(new BokehBlurProcessor(radius, components, gamma), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Convolution/BoxBlurExtensions.cs b/src/ImageSharp/Processing/Extensions/Convolution/BoxBlurExtensions.cs index 85b4888f0d..6611af742b 100644 --- a/src/ImageSharp/Processing/Extensions/Convolution/BoxBlurExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Convolution/BoxBlurExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Convolution; @@ -14,36 +14,36 @@ public static class BoxBlurExtensions /// /// Applies a box blur to the image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext BoxBlur(this IImageProcessingContext source) => source.ApplyProcessor(new BoxBlurProcessor()); /// /// Applies a box blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'radius' value representing the size of the area to sample. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius) => source.ApplyProcessor(new BoxBlurProcessor(radius)); /// /// Applies a box blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'radius' value representing the size of the area to sample. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius, Rectangle rectangle) => source.ApplyProcessor(new BoxBlurProcessor(radius), rectangle); /// /// Applies a box blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'radius' value representing the size of the area to sample. /// /// The structure that specifies the portion of the image object to alter. @@ -54,7 +54,7 @@ public static class BoxBlurExtensions /// /// The to use when mapping the pixels outside of the border, in Y direction. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BoxBlur(this IImageProcessingContext source, int radius, Rectangle rectangle, BorderWrappingMode borderWrapModeX, BorderWrappingMode borderWrapModeY) { var processor = new BoxBlurProcessor(radius, borderWrapModeX, borderWrapModeY); diff --git a/src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs b/src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs index 7f57ae9837..b044c3966f 100644 --- a/src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Convolution/DetectEdgesExtensions.cs @@ -14,8 +14,8 @@ public static class DetectEdgesExtensions /// Detects any edges within the image. /// Uses the kernel operating in grayscale mode. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext DetectEdges(this IImageProcessingContext source) => DetectEdges(source, KnownEdgeDetectorKernels.Sobel); @@ -23,11 +23,11 @@ public static class DetectEdgesExtensions /// Detects any edges within the image. /// Uses the kernel operating in grayscale mode. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, Rectangle rectangle) => @@ -36,9 +36,9 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image operating in grayscale mode. /// - /// The image this method extends. + /// The current image processing context. /// The 2D edge detector kernel. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetector2DKernel kernel) => @@ -47,12 +47,12 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image using a . /// - /// The image this method extends. + /// The current image processing context. /// The 2D edge detector kernel. /// /// Whether to convert the image to grayscale before performing edge detection. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetector2DKernel kernel, @@ -66,12 +66,12 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image operating in grayscale mode. /// - /// The image this method extends. + /// The current image processing context. /// The 2D edge detector kernel. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetector2DKernel kernel, @@ -81,7 +81,7 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image using a . /// - /// The image this method extends. + /// The current image processing context. /// The 2D edge detector kernel. /// /// Whether to convert the image to grayscale before performing edge detection. @@ -89,7 +89,7 @@ public static class DetectEdgesExtensions /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetector2DKernel kernel, @@ -104,9 +104,9 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image operating in grayscale mode. /// - /// The image this method extends. + /// The current image processing context. /// The edge detector kernel. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectorKernel kernel) => @@ -115,12 +115,12 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image using a . /// - /// The image this method extends. + /// The current image processing context. /// The edge detector kernel. /// /// Whether to convert the image to grayscale before performing edge detection. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectorKernel kernel, @@ -134,12 +134,12 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image operating in grayscale mode. /// - /// The image this method extends. + /// The current image processing context. /// The edge detector kernel. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectorKernel kernel, @@ -149,7 +149,7 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image using a . /// - /// The image this method extends. + /// The current image processing context. /// The edge detector kernel. /// /// Whether to convert the image to grayscale before performing edge detection. @@ -157,7 +157,7 @@ public static class DetectEdgesExtensions /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectorKernel kernel, @@ -172,9 +172,9 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image operating in grayscale mode. /// - /// The image this method extends. + /// The current image processing context. /// Thecompass edge detector kernel. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectorCompassKernel kernel) => @@ -183,12 +183,12 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image using a . /// - /// The image this method extends. + /// The current image processing context. /// Thecompass edge detector kernel. /// /// Whether to convert the image to grayscale before performing edge detection. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectorCompassKernel kernel, @@ -202,12 +202,12 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image operating in grayscale mode. /// - /// The image this method extends. + /// The current image processing context. /// Thecompass edge detector kernel. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectorCompassKernel kernel, @@ -217,7 +217,7 @@ public static class DetectEdgesExtensions /// /// Detects any edges within the image using a . /// - /// The image this method extends. + /// The current image processing context. /// Thecompass edge detector kernel. /// /// Whether to convert the image to grayscale before performing edge detection. @@ -225,7 +225,7 @@ public static class DetectEdgesExtensions /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext DetectEdges( this IImageProcessingContext source, EdgeDetectorCompassKernel kernel, diff --git a/src/ImageSharp/Processing/Extensions/Convolution/GaussianBlurExtensions.cs b/src/ImageSharp/Processing/Extensions/Convolution/GaussianBlurExtensions.cs index 9ea4e24af4..b851482008 100644 --- a/src/ImageSharp/Processing/Extensions/Convolution/GaussianBlurExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Convolution/GaussianBlurExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Convolution; @@ -14,36 +14,36 @@ public static class GaussianBlurExtensions /// /// Applies a Gaussian blur to the image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source) => source.ApplyProcessor(new GaussianBlurProcessor()); /// /// Applies a Gaussian blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'sigma' value representing the weight of the blur. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma) => source.ApplyProcessor(new GaussianBlurProcessor(sigma)); /// /// Applies a Gaussian blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'sigma' value representing the weight of the blur. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma, Rectangle rectangle) => source.ApplyProcessor(new GaussianBlurProcessor(sigma), rectangle); /// /// Applies a Gaussian blur to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'sigma' value representing the weight of the blur. /// /// The structure that specifies the portion of the image object to alter. @@ -54,7 +54,7 @@ public static class GaussianBlurExtensions /// /// The to use when mapping the pixels outside of the border, in Y direction. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext GaussianBlur(this IImageProcessingContext source, float sigma, Rectangle rectangle, BorderWrappingMode borderWrapModeX, BorderWrappingMode borderWrapModeY) { var processor = new GaussianBlurProcessor(sigma, borderWrapModeX, borderWrapModeY); diff --git a/src/ImageSharp/Processing/Extensions/Convolution/GaussianSharpenExtensions.cs b/src/ImageSharp/Processing/Extensions/Convolution/GaussianSharpenExtensions.cs index 70b8e6f439..4a94df0963 100644 --- a/src/ImageSharp/Processing/Extensions/Convolution/GaussianSharpenExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Convolution/GaussianSharpenExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Convolution; @@ -14,29 +14,29 @@ public static class GaussianSharpenExtensions /// /// Applies a Gaussian sharpening filter to the image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source) => source.ApplyProcessor(new GaussianSharpenProcessor()); /// /// Applies a Gaussian sharpening filter to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'sigma' value representing the weight of the blur. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma) => source.ApplyProcessor(new GaussianSharpenProcessor(sigma)); /// /// Applies a Gaussian sharpening filter to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'sigma' value representing the weight of the blur. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext GaussianSharpen( this IImageProcessingContext source, float sigma, @@ -46,7 +46,7 @@ public static class GaussianSharpenExtensions /// /// Applies a Gaussian sharpening filter to the image. /// - /// The image this method extends. + /// The current image processing context. /// The 'sigma' value representing the weight of the blur. /// /// The structure that specifies the portion of the image object to alter. @@ -57,7 +57,7 @@ public static class GaussianSharpenExtensions /// /// The to use when mapping the pixels outside of the border, in Y direction. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext GaussianSharpen(this IImageProcessingContext source, float sigma, Rectangle rectangle, BorderWrappingMode borderWrapModeX, BorderWrappingMode borderWrapModeY) { var processor = new GaussianSharpenProcessor(sigma, borderWrapModeX, borderWrapModeY); diff --git a/src/ImageSharp/Processing/Extensions/Convolution/MedianBlurExtensions.cs b/src/ImageSharp/Processing/Extensions/Convolution/MedianBlurExtensions.cs index 60a80d35e5..a08a398b75 100644 --- a/src/ImageSharp/Processing/Extensions/Convolution/MedianBlurExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Convolution/MedianBlurExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Convolution; @@ -14,19 +14,19 @@ public static class MedianBlurExtensions /// /// Applies a median blur on the image. /// - /// The image this method extends. + /// The current image processing context. /// The radius of the area to find the median for. /// /// Whether the filter is applied to alpha as well as the color channels. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext MedianBlur(this IImageProcessingContext source, int radius, bool preserveAlpha) => source.ApplyProcessor(new MedianBlurProcessor(radius, preserveAlpha)); /// /// Applies a median blur on the image. /// - /// The image this method extends. + /// The current image processing context. /// The radius of the area to find the median for. /// /// Whether the filter is applied to alpha as well as the color channels. @@ -34,7 +34,7 @@ public static class MedianBlurExtensions /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext MedianBlur(this IImageProcessingContext source, int radius, bool preserveAlpha, Rectangle rectangle) => source.ApplyProcessor(new MedianBlurProcessor(radius, preserveAlpha), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Dithering/DitherExtensions.cs b/src/ImageSharp/Processing/Extensions/Dithering/DitherExtensions.cs index 3eaeb715d3..fbeddb479d 100644 --- a/src/ImageSharp/Processing/Extensions/Dithering/DitherExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Dithering/DitherExtensions.cs @@ -14,17 +14,17 @@ public static class DitherExtensions /// /// Dithers the image reducing it to a web-safe palette using . /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Dither(this IImageProcessingContext source) => Dither(source, KnownDitherings.Bayer8x8); /// /// Dithers the image reducing it to a web-safe palette. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither( this IImageProcessingContext source, IDither dither) => @@ -33,10 +33,10 @@ public static class DitherExtensions /// /// Dithers the image reducing it to a web-safe palette. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// The dithering scale used to adjust the amount of dither. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither( this IImageProcessingContext source, IDither dither, @@ -46,10 +46,10 @@ public static class DitherExtensions /// /// Dithers the image reducing it to the given palette. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// The palette to select substitute colors from. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither( this IImageProcessingContext source, IDither dither, @@ -59,11 +59,11 @@ public static class DitherExtensions /// /// Dithers the image reducing it to the given palette. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// The dithering scale used to adjust the amount of dither. /// The palette to select substitute colors from. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither( this IImageProcessingContext source, IDither dither, @@ -74,23 +74,23 @@ public static class DitherExtensions /// /// Dithers the image reducing it to a web-safe palette using . /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither(this IImageProcessingContext source, Rectangle rectangle) => Dither(source, KnownDitherings.Bayer8x8, rectangle); /// /// Dithers the image reducing it to a web-safe palette. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither( this IImageProcessingContext source, IDither dither, @@ -100,13 +100,13 @@ public static class DitherExtensions /// /// Dithers the image reducing it to a web-safe palette. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// The dithering scale used to adjust the amount of dither. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither( this IImageProcessingContext source, IDither dither, @@ -117,13 +117,13 @@ public static class DitherExtensions /// /// Dithers the image reducing it to the given palette. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// The palette to select substitute colors from. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither( this IImageProcessingContext source, IDither dither, @@ -134,14 +134,14 @@ public static class DitherExtensions /// /// Dithers the image reducing it to the given palette. /// - /// The image this method extends. + /// The current image processing context. /// The ordered ditherer. /// The dithering scale used to adjust the amount of dither. /// The palette to select substitute colors from. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Dither( this IImageProcessingContext source, IDither dither, diff --git a/src/ImageSharp/Processing/Extensions/Effects/OilPaintExtensions.cs b/src/ImageSharp/Processing/Extensions/Effects/OilPaintExtensions.cs index e29b39478f..2c8d76c831 100644 --- a/src/ImageSharp/Processing/Extensions/Effects/OilPaintExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Effects/OilPaintExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Effects; @@ -15,29 +15,29 @@ public static class OilPaintExtensions /// Alters the colors of the image recreating an oil painting effect with levels and brushSize /// set to 10 and 15 respectively. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext OilPaint(this IImageProcessingContext source) => OilPaint(source, 10, 15); /// /// Alters the colors of the image recreating an oil painting effect with levels and brushSize /// set to 10 and 15 respectively. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext OilPaint(this IImageProcessingContext source, Rectangle rectangle) => OilPaint(source, 10, 15, rectangle); /// /// Alters the colors of the image recreating an oil painting effect. /// - /// The image this method extends. + /// The current image processing context. /// The number of intensity levels. Higher values result in a broader range of color intensities forming part of the result image. /// The number of neighboring pixels used in calculating each individual pixel value. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext OilPaint(this IImageProcessingContext source, int levels, int brushSize) => source.ApplyProcessor(new OilPaintingProcessor(levels, brushSize)); @@ -45,13 +45,13 @@ public static class OilPaintExtensions /// /// Alters the colors of the image recreating an oil painting effect. /// - /// The image this method extends. + /// The current image processing context. /// The number of intensity levels. Higher values result in a broader range of color intensities forming part of the result image. /// The number of neighboring pixels used in calculating each individual pixel value. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext OilPaint( this IImageProcessingContext source, int levels, diff --git a/src/ImageSharp/Processing/Extensions/Effects/PixelRowDelegateExtensions.cs b/src/ImageSharp/Processing/Extensions/Effects/PixelRowDelegateExtensions.cs index e7b5d7623e..703b1b2fbb 100644 --- a/src/ImageSharp/Processing/Extensions/Effects/PixelRowDelegateExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Effects/PixelRowDelegateExtensions.cs @@ -14,88 +14,88 @@ public static class PixelRowDelegateExtensions /// /// Applies a user defined processing delegate to the image. /// - /// The image this method extends. + /// The current image processing context. /// The user defined processing delegate to use to modify image rows. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ProcessPixelRowsAsVector4(this IImageProcessingContext source, PixelRowOperation rowOperation) => ProcessPixelRowsAsVector4(source, rowOperation, PixelConversionModifiers.None); /// /// Applies a user defined processing delegate to the image. /// - /// The image this method extends. + /// The current image processing context. /// The user defined processing delegate to use to modify image rows. /// The to apply during the pixel conversions. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ProcessPixelRowsAsVector4(this IImageProcessingContext source, PixelRowOperation rowOperation, PixelConversionModifiers modifiers) => source.ApplyProcessor(new PixelRowDelegateProcessor(rowOperation, modifiers)); /// /// Applies a user defined processing delegate to the image. /// - /// The image this method extends. + /// The current image processing context. /// The user defined processing delegate to use to modify image rows. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ProcessPixelRowsAsVector4(this IImageProcessingContext source, PixelRowOperation rowOperation, Rectangle rectangle) => ProcessPixelRowsAsVector4(source, rowOperation, rectangle, PixelConversionModifiers.None); /// /// Applies a user defined processing delegate to the image. /// - /// The image this method extends. + /// The current image processing context. /// The user defined processing delegate to use to modify image rows. /// /// The structure that specifies the portion of the image object to alter. /// /// The to apply during the pixel conversions. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ProcessPixelRowsAsVector4(this IImageProcessingContext source, PixelRowOperation rowOperation, Rectangle rectangle, PixelConversionModifiers modifiers) => source.ApplyProcessor(new PixelRowDelegateProcessor(rowOperation, modifiers), rectangle); /// /// Applies a user defined processing delegate to the image. /// - /// The image this method extends. + /// The current image processing context. /// The user defined processing delegate to use to modify image rows. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ProcessPixelRowsAsVector4(this IImageProcessingContext source, PixelRowOperation rowOperation) => ProcessPixelRowsAsVector4(source, rowOperation, PixelConversionModifiers.None); /// /// Applies a user defined processing delegate to the image. /// - /// The image this method extends. + /// The current image processing context. /// The user defined processing delegate to use to modify image rows. /// The to apply during the pixel conversions. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ProcessPixelRowsAsVector4(this IImageProcessingContext source, PixelRowOperation rowOperation, PixelConversionModifiers modifiers) => source.ApplyProcessor(new PositionAwarePixelRowDelegateProcessor(rowOperation, modifiers)); /// /// Applies a user defined processing delegate to the image. /// - /// The image this method extends. + /// The current image processing context. /// The user defined processing delegate to use to modify image rows. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ProcessPixelRowsAsVector4(this IImageProcessingContext source, PixelRowOperation rowOperation, Rectangle rectangle) => ProcessPixelRowsAsVector4(source, rowOperation, rectangle, PixelConversionModifiers.None); /// /// Applies a user defined processing delegate to the image. /// - /// The image this method extends. + /// The current image processing context. /// The user defined processing delegate to use to modify image rows. /// /// The structure that specifies the portion of the image object to alter. /// /// The to apply during the pixel conversions. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ProcessPixelRowsAsVector4(this IImageProcessingContext source, PixelRowOperation rowOperation, Rectangle rectangle, PixelConversionModifiers modifiers) => source.ApplyProcessor(new PositionAwarePixelRowDelegateProcessor(rowOperation, modifiers), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Effects/PixelateExtensions.cs b/src/ImageSharp/Processing/Extensions/Effects/PixelateExtensions.cs index 17654a2061..584887ea17 100644 --- a/src/ImageSharp/Processing/Extensions/Effects/PixelateExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Effects/PixelateExtensions.cs @@ -14,28 +14,28 @@ public static class PixelateExtensions /// /// Pixelates an image with the given pixel size. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Pixelate(this IImageProcessingContext source) => Pixelate(source, 4); /// /// Pixelates an image with the given pixel size. /// - /// The image this method extends. + /// The current image processing context. /// The size of the pixels. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Pixelate(this IImageProcessingContext source, int size) => source.ApplyProcessor(new PixelateProcessor(size)); /// /// Pixelates an image with the given pixel size. /// - /// The image this method extends. + /// The current image processing context. /// The size of the pixels. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Pixelate( this IImageProcessingContext source, int size, diff --git a/src/ImageSharp/Processing/Extensions/Filters/BlackWhiteExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/BlackWhiteExtensions.cs index 54f2d2143e..8e44928f9e 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/BlackWhiteExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/BlackWhiteExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -14,19 +14,19 @@ public static class BlackWhiteExtensions /// /// Applies black and white toning to the image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext BlackWhite(this IImageProcessingContext source) => source.ApplyProcessor(new BlackWhiteProcessor()); /// /// Applies black and white toning to the image. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BlackWhite(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new BlackWhiteProcessor(), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/BrightnessExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/BrightnessExtensions.cs index e53f22040f..35140c2140 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/BrightnessExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/BrightnessExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -18,9 +18,9 @@ public static class BrightnessExtensions /// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing brighter results. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be greater than or equal to 0. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Brightness(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new BrightnessProcessor(amount)); @@ -31,12 +31,12 @@ public static class BrightnessExtensions /// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing brighter results. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be greater than or equal to 0. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Brightness(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new BrightnessProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/ColorBlindnessExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/ColorBlindnessExtensions.cs index 73c3c29a91..ed1c07a431 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/ColorBlindnessExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/ColorBlindnessExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors; @@ -15,21 +15,21 @@ public static class ColorBlindnessExtensions /// /// Applies the given colorblindness simulator to the image. /// - /// The image this method extends. + /// The current image processing context. /// The type of color blindness simulator to apply. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ColorBlindness(this IImageProcessingContext source, ColorBlindnessMode colorBlindness) => source.ApplyProcessor(GetProcessor(colorBlindness)); /// /// Applies the given colorblindness simulator to the image. /// - /// The image this method extends. + /// The current image processing context. /// The type of color blindness simulator to apply. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext ColorBlindness(this IImageProcessingContext source, ColorBlindnessMode colorBlindnessMode, Rectangle rectangle) => source.ApplyProcessor(GetProcessor(colorBlindnessMode), rectangle); diff --git a/src/ImageSharp/Processing/Extensions/Filters/ContrastExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/ContrastExtensions.cs index 5ed5c9a21d..4dd4707bc1 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/ContrastExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/ContrastExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -18,9 +18,9 @@ public static class ContrastExtensions /// A value of 0 will create an image that is completely gray. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing results with more contrast. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be greater than or equal to 0. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Contrast(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new ContrastProcessor(amount)); @@ -31,12 +31,12 @@ public static class ContrastExtensions /// A value of 0 will create an image that is completely gray. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing results with more contrast. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be greater than or equal to 0. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Contrast(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new ContrastProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/FilterExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/FilterExtensions.cs index 051afebc97..387307b3df 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/FilterExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/FilterExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -14,21 +14,21 @@ public static class FilterExtensions /// /// Filters an image by the given color matrix /// - /// The image this method extends. + /// The current image processing context. /// The filter color matrix - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix) => source.ApplyProcessor(new FilterProcessor(matrix)); /// /// Filters an image by the given color matrix /// - /// The image this method extends. + /// The current image processing context. /// The filter color matrix /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Filter(this IImageProcessingContext source, ColorMatrix matrix, Rectangle rectangle) => source.ApplyProcessor(new FilterProcessor(matrix), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/GrayscaleExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/GrayscaleExtensions.cs index 88633719a1..86ef74394e 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/GrayscaleExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/GrayscaleExtensions.cs @@ -15,7 +15,7 @@ public static class GrayscaleExtensions /// /// Applies grayscale toning to the image. /// - /// The image this method extends. + /// The current image processing context. /// The . public static IImageProcessingContext Grayscale(this IImageProcessingContext source) => Grayscale(source, GrayscaleMode.Bt709); @@ -23,7 +23,7 @@ public static class GrayscaleExtensions /// /// Applies grayscale toning to the image using the given amount. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be between 0 and 1. /// The . public static IImageProcessingContext Grayscale(this IImageProcessingContext source, float amount) @@ -32,7 +32,7 @@ public static class GrayscaleExtensions /// /// Applies grayscale toning to the image with the given . /// - /// The image this method extends. + /// The current image processing context. /// The formula to apply to perform the operation. /// The . public static IImageProcessingContext Grayscale(this IImageProcessingContext source, GrayscaleMode mode) @@ -41,7 +41,7 @@ public static class GrayscaleExtensions /// /// Applies grayscale toning to the image with the given using the given amount. /// - /// The image this method extends. + /// The current image processing context. /// The formula to apply to perform the operation. /// The proportion of the conversion. Must be between 0 and 1. /// The . @@ -58,7 +58,7 @@ public static class GrayscaleExtensions /// /// Applies grayscale toning to the image. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// @@ -69,7 +69,7 @@ public static class GrayscaleExtensions /// /// Applies grayscale toning to the image using the given amount. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. @@ -81,7 +81,7 @@ public static class GrayscaleExtensions /// /// Applies grayscale toning to the image. /// - /// The image this method extends. + /// The current image processing context. /// The formula to apply to perform the operation. /// /// The structure that specifies the portion of the image object to alter. @@ -93,7 +93,7 @@ public static class GrayscaleExtensions /// /// Applies grayscale toning to the image using the given amount. /// - /// The image this method extends. + /// The current image processing context. /// The formula to apply to perform the operation. /// The proportion of the conversion. Must be between 0 and 1. /// diff --git a/src/ImageSharp/Processing/Extensions/Filters/HueExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/HueExtensions.cs index 3ec339e9c9..a493a6f828 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/HueExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/HueExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -14,21 +14,21 @@ public static class HueExtensions /// /// Alters the hue component of the image. /// - /// The image this method extends. + /// The current image processing context. /// The rotation angle in degrees to adjust the hue. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Hue(this IImageProcessingContext source, float degrees) => source.ApplyProcessor(new HueProcessor(degrees)); /// /// Alters the hue component of the image. /// - /// The image this method extends. + /// The current image processing context. /// The rotation angle in degrees to adjust the hue. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Hue(this IImageProcessingContext source, float degrees, Rectangle rectangle) => source.ApplyProcessor(new HueProcessor(degrees), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/InvertExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/InvertExtensions.cs index 3c7845ec83..6b42e7da43 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/InvertExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/InvertExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -14,19 +14,19 @@ public static class InvertExtensions /// /// Inverts the colors of the image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Invert(this IImageProcessingContext source) => source.ApplyProcessor(new InvertProcessor(1F)); /// /// Inverts the colors of the image. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Invert(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new InvertProcessor(1F), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/KodachromeExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/KodachromeExtensions.cs index 8aa8260676..5c64e2b785 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/KodachromeExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/KodachromeExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -14,19 +14,19 @@ public static class KodachromeExtensions /// /// Alters the colors of the image recreating an old Kodachrome camera effect. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Kodachrome(this IImageProcessingContext source) => source.ApplyProcessor(new KodachromeProcessor()); /// /// Alters the colors of the image recreating an old Kodachrome camera effect. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Kodachrome(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new KodachromeProcessor(), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/LightnessExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/LightnessExtensions.cs index fb937d9728..8542027702 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/LightnessExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/LightnessExtensions.cs @@ -18,9 +18,9 @@ public static class LightnessExtensions /// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing lighter results. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be greater than or equal to 0. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Lightness(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new LightnessProcessor(amount)); @@ -31,12 +31,12 @@ public static class LightnessExtensions /// A value of 0 will create an image that is completely black. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of an amount over 1 are allowed, providing lighter results. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be greater than or equal to 0. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Lightness(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new LightnessProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/LomographExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/LomographExtensions.cs index 816647bd42..8942fdde01 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/LomographExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/LomographExtensions.cs @@ -14,19 +14,19 @@ public static class LomographExtensions /// /// Alters the colors of the image recreating an old Lomograph camera effect. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Lomograph(this IImageProcessingContext source) => source.ApplyProcessor(new LomographProcessor(source.GetGraphicsOptions())); /// /// Alters the colors of the image recreating an old Lomograph camera effect. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Lomograph(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new LomographProcessor(source.GetGraphicsOptions()), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/OpacityExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/OpacityExtensions.cs index e704dd763c..467b98d52b 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/OpacityExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/OpacityExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -14,21 +14,21 @@ public static class OpacityExtensions /// /// Multiplies the alpha component of the image. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be between 0 and 1. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Opacity(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new OpacityProcessor(amount)); /// /// Multiplies the alpha component of the image. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Opacity(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new OpacityProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/PolaroidExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/PolaroidExtensions.cs index bab05c0365..41678e4313 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/PolaroidExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/PolaroidExtensions.cs @@ -14,19 +14,19 @@ public static class PolaroidExtensions /// /// Alters the colors of the image recreating an old Polaroid camera effect. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Polaroid(this IImageProcessingContext source) => source.ApplyProcessor(new PolaroidProcessor(source.GetGraphicsOptions())); /// /// Alters the colors of the image recreating an old Polaroid camera effect. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Polaroid(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new PolaroidProcessor(source.GetGraphicsOptions()), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/SaturateExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/SaturateExtensions.cs index 03e6ddcba5..5bf9c737ee 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/SaturateExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/SaturateExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -18,9 +18,9 @@ public static class SaturateExtensions /// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be greater than or equal to 0. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Saturate(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new SaturateProcessor(amount)); @@ -31,12 +31,12 @@ public static class SaturateExtensions /// A value of 0 is completely un-saturated. A value of 1 leaves the input unchanged. /// Other values are linear multipliers on the effect. Values of amount over 1 are allowed, providing super-saturated results /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be greater than or equal to 0. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Saturate(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new SaturateProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Filters/SepiaExtensions.cs b/src/ImageSharp/Processing/Extensions/Filters/SepiaExtensions.cs index 01ddccba0d..af00b9b329 100644 --- a/src/ImageSharp/Processing/Extensions/Filters/SepiaExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Filters/SepiaExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Filters; @@ -14,40 +14,40 @@ public static class SepiaExtensions /// /// Applies sepia toning to the image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Sepia(this IImageProcessingContext source) => Sepia(source, 1F); /// /// Applies sepia toning to the image using the given amount. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be between 0 and 1. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Sepia(this IImageProcessingContext source, float amount) => source.ApplyProcessor(new SepiaProcessor(amount)); /// /// Applies sepia toning to the image. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Sepia(this IImageProcessingContext source, Rectangle rectangle) => Sepia(source, 1F, rectangle); /// /// Applies sepia toning to the image. /// - /// The image this method extends. + /// The current image processing context. /// The proportion of the conversion. Must be between 0 and 1. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Sepia(this IImageProcessingContext source, float amount, Rectangle rectangle) => source.ApplyProcessor(new SepiaProcessor(amount), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Normalization/HistogramEqualizationExtensions.cs b/src/ImageSharp/Processing/Extensions/Normalization/HistogramEqualizationExtensions.cs index ab5b8e3e1b..d7f4ba3594 100644 --- a/src/ImageSharp/Processing/Extensions/Normalization/HistogramEqualizationExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Normalization/HistogramEqualizationExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Normalization; @@ -13,17 +13,17 @@ public static class HistogramEqualizationExtensions /// /// Equalizes the histogram of an image to increases the contrast. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext HistogramEqualization(this IImageProcessingContext source) => HistogramEqualization(source, new HistogramEqualizationOptions()); /// /// Equalizes the histogram of an image to increases the contrast. /// - /// The image this method extends. + /// The current image processing context. /// The histogram equalization options to use. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext HistogramEqualization( this IImageProcessingContext source, HistogramEqualizationOptions options) => diff --git a/src/ImageSharp/Processing/Extensions/Overlays/BackgroundColorExtensions.cs b/src/ImageSharp/Processing/Extensions/Overlays/BackgroundColorExtensions.cs index 4369f45326..938c880f60 100644 --- a/src/ImageSharp/Processing/Extensions/Overlays/BackgroundColorExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Overlays/BackgroundColorExtensions.cs @@ -14,21 +14,21 @@ public static class BackgroundColorExtensions /// /// Replaces the background color of image with the given one. /// - /// The image this method extends. + /// The current image processing context. /// The color to set as the background. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BackgroundColor(this IImageProcessingContext source, Color color) => BackgroundColor(source, source.GetGraphicsOptions(), color); /// /// Replaces the background color of image with the given one. /// - /// The image this method extends. + /// The current image processing context. /// The color to set as the background. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BackgroundColor( this IImageProcessingContext source, Color color, @@ -38,10 +38,10 @@ public static class BackgroundColorExtensions /// /// Replaces the background color of image with the given one. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting pixel blending. /// The color to set as the background. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BackgroundColor( this IImageProcessingContext source, GraphicsOptions options, @@ -51,13 +51,13 @@ public static class BackgroundColorExtensions /// /// Replaces the background color of image with the given one. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting pixel blending. /// The color to set as the background. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext BackgroundColor( this IImageProcessingContext source, GraphicsOptions options, diff --git a/src/ImageSharp/Processing/Extensions/Overlays/GlowExtensions.cs b/src/ImageSharp/Processing/Extensions/Overlays/GlowExtensions.cs index c588ae9647..9e00f5b304 100644 --- a/src/ImageSharp/Processing/Extensions/Overlays/GlowExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Overlays/GlowExtensions.cs @@ -14,17 +14,17 @@ public static class GlowExtensions /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Glow(this IImageProcessingContext source) => Glow(source, source.GetGraphicsOptions()); /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The color to set as the glow. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow(this IImageProcessingContext source, Color color) { return Glow(source, source.GetGraphicsOptions(), color); @@ -33,33 +33,33 @@ public static class GlowExtensions /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The the radius. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow(this IImageProcessingContext source, float radius) => Glow(source, source.GetGraphicsOptions(), radius); /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow(this IImageProcessingContext source, Rectangle rectangle) => source.Glow(source.GetGraphicsOptions(), rectangle); /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The color to set as the glow. /// The the radius. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow( this IImageProcessingContext source, Color color, @@ -70,19 +70,19 @@ public static class GlowExtensions /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting things like blending. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow(this IImageProcessingContext source, GraphicsOptions options) => source.Glow(options, Color.Black, ValueSize.PercentageOfWidth(0.5f)); /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting things like blending. /// The color to set as the glow. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow( this IImageProcessingContext source, GraphicsOptions options, @@ -92,10 +92,10 @@ public static class GlowExtensions /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting things like blending. /// The the radius. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow( this IImageProcessingContext source, GraphicsOptions options, @@ -105,12 +105,12 @@ public static class GlowExtensions /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting things like blending. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow( this IImageProcessingContext source, GraphicsOptions options, @@ -120,14 +120,14 @@ public static class GlowExtensions /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting things like blending. /// The color to set as the glow. /// The the radius. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Glow( this IImageProcessingContext source, GraphicsOptions options, @@ -139,14 +139,14 @@ public static class GlowExtensions /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting things like blending. /// The color to set as the glow. /// The the radius. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . private static IImageProcessingContext Glow( this IImageProcessingContext source, GraphicsOptions options, @@ -158,11 +158,11 @@ public static class GlowExtensions /// /// Applies a radial glow effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting things like blending. /// The color to set as the glow. /// The the radius. - /// The to allow chaining of operations. + /// The . private static IImageProcessingContext Glow( this IImageProcessingContext source, GraphicsOptions options, diff --git a/src/ImageSharp/Processing/Extensions/Overlays/VignetteExtensions.cs b/src/ImageSharp/Processing/Extensions/Overlays/VignetteExtensions.cs index 379a2f32ab..fb9f79d411 100644 --- a/src/ImageSharp/Processing/Extensions/Overlays/VignetteExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Overlays/VignetteExtensions.cs @@ -14,27 +14,27 @@ public static class VignetteExtensions /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Vignette(this IImageProcessingContext source) => Vignette(source, source.GetGraphicsOptions()); /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The color to set as the vignette. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette(this IImageProcessingContext source, Color color) => Vignette(source, source.GetGraphicsOptions(), color); /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The the x-radius. /// The the y-radius. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette( this IImageProcessingContext source, float radiusX, @@ -44,25 +44,25 @@ public static class VignetteExtensions /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette(this IImageProcessingContext source, Rectangle rectangle) => Vignette(source, source.GetGraphicsOptions(), rectangle); /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The color to set as the vignette. /// The the x-radius. /// The the y-radius. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette( this IImageProcessingContext source, Color color, @@ -74,9 +74,9 @@ public static class VignetteExtensions /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting pixel blending. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette(this IImageProcessingContext source, GraphicsOptions options) => source.VignetteInternal( options, @@ -87,10 +87,10 @@ public static class VignetteExtensions /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting pixel blending. /// The color to set as the vignette. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette( this IImageProcessingContext source, GraphicsOptions options, @@ -104,11 +104,11 @@ public static class VignetteExtensions /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting pixel blending. /// The the x-radius. /// The the y-radius. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette( this IImageProcessingContext source, GraphicsOptions options, @@ -119,12 +119,12 @@ public static class VignetteExtensions /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting pixel blending. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette( this IImageProcessingContext source, GraphicsOptions options, @@ -139,7 +139,7 @@ public static class VignetteExtensions /// /// Applies a radial vignette effect to an image. /// - /// The image this method extends. + /// The current image processing context. /// The options effecting pixel blending. /// The color to set as the vignette. /// The the x-radius. @@ -147,7 +147,7 @@ public static class VignetteExtensions /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Vignette( this IImageProcessingContext source, GraphicsOptions options, diff --git a/src/ImageSharp/Processing/Extensions/Quantization/QuantizeExtensions.cs b/src/ImageSharp/Processing/Extensions/Quantization/QuantizeExtensions.cs index 559477a05e..bf6d2221f4 100644 --- a/src/ImageSharp/Processing/Extensions/Quantization/QuantizeExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Quantization/QuantizeExtensions.cs @@ -14,40 +14,40 @@ public static class QuantizeExtensions /// /// Applies quantization to the image using the . /// - /// The image this method extends. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext Quantize(this IImageProcessingContext source) => Quantize(source, KnownQuantizers.Octree); /// /// Applies quantization to the image. /// - /// The image this method extends. + /// The current image processing context. /// The quantizer to apply to perform the operation. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Quantize(this IImageProcessingContext source, IQuantizer quantizer) => source.ApplyProcessor(new QuantizeProcessor(quantizer)); /// /// Applies quantization to the image using the . /// - /// The image this method extends. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Quantize(this IImageProcessingContext source, Rectangle rectangle) => Quantize(source, KnownQuantizers.Octree, rectangle); /// /// Applies quantization to the image. /// - /// The image this method extends. + /// The current image processing context. /// The quantizer to apply to perform the operation. /// /// The structure that specifies the portion of the image object to alter. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Quantize(this IImageProcessingContext source, IQuantizer quantizer, Rectangle rectangle) => source.ApplyProcessor(new QuantizeProcessor(quantizer), rectangle); } diff --git a/src/ImageSharp/Processing/Extensions/Transforms/AutoOrientExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/AutoOrientExtensions.cs index a7b8dbf43f..fcd0023e53 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/AutoOrientExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/AutoOrientExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Transforms; @@ -14,8 +14,8 @@ public static class AutoOrientExtensions /// /// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image. /// - /// The image to auto rotate. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext AutoOrient(this IImageProcessingContext source) => source.ApplyProcessor(new AutoOrientProcessor()); } diff --git a/src/ImageSharp/Processing/Extensions/Transforms/CropExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/CropExtensions.cs index 434aeb6582..3025806d4f 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/CropExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/CropExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Transforms; @@ -14,21 +14,21 @@ public static class CropExtensions /// /// Crops an image to the given width and height. /// - /// The image to resize. + /// The current image processing context. /// The target image width. /// The target image height. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Crop(this IImageProcessingContext source, int width, int height) => Crop(source, new Rectangle(0, 0, width, height)); /// /// Crops an image to the given rectangle. /// - /// The image to crop. + /// The current image processing context. /// /// The structure that specifies the portion of the image object to retain. /// - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Crop(this IImageProcessingContext source, Rectangle cropRectangle) => source.ApplyProcessor(new CropProcessor(cropRectangle, source.GetCurrentSize())); } diff --git a/src/ImageSharp/Processing/Extensions/Transforms/EntropyCropExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/EntropyCropExtensions.cs index 14e7f9f134..6461a4e8aa 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/EntropyCropExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/EntropyCropExtensions.cs @@ -14,17 +14,17 @@ public static class EntropyCropExtensions /// /// Crops an image to the area of greatest entropy using a threshold for entropic density of .5F. /// - /// The image to crop. - /// The to allow chaining of operations. + /// The current image processing context. + /// The . public static IImageProcessingContext EntropyCrop(this IImageProcessingContext source) => source.ApplyProcessor(new EntropyCropProcessor()); /// /// Crops an image to the area of greatest entropy. /// - /// The image to crop. + /// The current image processing context. /// The threshold for entropic density. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext EntropyCrop(this IImageProcessingContext source, float threshold) => source.ApplyProcessor(new EntropyCropProcessor(threshold)); } diff --git a/src/ImageSharp/Processing/Extensions/Transforms/FlipExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/FlipExtensions.cs index 243d818b84..3828572a60 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/FlipExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/FlipExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Transforms; @@ -14,9 +14,9 @@ public static class FlipExtensions /// /// Flips an image by the given instructions. /// - /// The image to rotate, flip, or both. + /// The current image processing context. /// The to perform the flip. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Flip(this IImageProcessingContext source, FlipMode flipMode) => source.ApplyProcessor(new FlipProcessor(flipMode)); } diff --git a/src/ImageSharp/Processing/Extensions/Transforms/PadExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/PadExtensions.cs index dfade98475..b6db0172dc 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/PadExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/PadExtensions.cs @@ -12,21 +12,21 @@ public static class PadExtensions /// /// Evenly pads an image to fit the new dimensions. /// - /// The source image to pad. + /// The current image processing context. /// The new width. /// The new height. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Pad(this IImageProcessingContext source, int width, int height) => source.Pad(width, height, default); /// /// Evenly pads an image to fit the new dimensions with the given background color. /// - /// The source image to pad. + /// The current image processing context. /// The new width. /// The new height. /// The background color with which to pad the image. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Pad(this IImageProcessingContext source, int width, int height, Color color) { Size size = source.GetCurrentSize(); diff --git a/src/ImageSharp/Processing/Extensions/Transforms/ResizeExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/ResizeExtensions.cs index 7580f64690..01f296d096 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/ResizeExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/ResizeExtensions.cs @@ -14,9 +14,9 @@ public static class ResizeExtensions /// /// Resizes an image to the given . /// - /// The image to resize. + /// The current image processing context. /// The target image size. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size) => Resize(source, size.Width, size.Height, KnownResamplers.Bicubic, false); @@ -24,10 +24,10 @@ public static class ResizeExtensions /// /// Resizes an image to the given . /// - /// The image to resize. + /// The current image processing context. /// The target image size. /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size, bool compand) => Resize(source, size.Width, size.Height, KnownResamplers.Bicubic, compand); @@ -35,10 +35,10 @@ public static class ResizeExtensions /// /// Resizes an image to the given width and height. /// - /// The image to resize. + /// The current image processing context. /// The target image width. /// The target image height. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height) => Resize(source, width, height, KnownResamplers.Bicubic, false); @@ -46,11 +46,11 @@ public static class ResizeExtensions /// /// Resizes an image to the given width and height. /// - /// The image to resize. + /// The current image processing context. /// The target image width. /// The target image height. /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, bool compand) => Resize(source, width, height, KnownResamplers.Bicubic, compand); @@ -58,11 +58,11 @@ public static class ResizeExtensions /// /// Resizes an image to the given width and height with the given sampler. /// - /// The image to resize. + /// The current image processing context. /// The target image width. /// The target image height. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, IResampler sampler) => Resize(source, width, height, sampler, false); @@ -70,11 +70,11 @@ public static class ResizeExtensions /// /// Resizes an image to the given width and height with the given sampler. /// - /// The image to resize. + /// The current image processing context. /// The target image size. /// The to perform the resampling. /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, Size size, IResampler sampler, bool compand) => Resize(source, size.Width, size.Height, sampler, new Rectangle(0, 0, size.Width, size.Height), compand); @@ -82,12 +82,12 @@ public static class ResizeExtensions /// /// Resizes an image to the given width and height with the given sampler. /// - /// The image to resize. + /// The current image processing context. /// The target image width. /// The target image height. /// The to perform the resampling. /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, int width, int height, IResampler sampler, bool compand) => Resize(source, width, height, sampler, new Rectangle(0, 0, width, height), compand); @@ -96,7 +96,7 @@ public static class ResizeExtensions /// Resizes an image to the given width and height with the given sampler and /// source rectangle. /// - /// The image to resize. + /// The current image processing context. /// The target image width. /// The target image height. /// The to perform the resampling. @@ -107,7 +107,7 @@ public static class ResizeExtensions /// The structure that specifies the portion of the target image object to draw to. /// /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize( this IImageProcessingContext source, @@ -133,7 +133,7 @@ public static class ResizeExtensions /// /// Resizes an image to the given width and height with the given sampler and source rectangle. /// - /// The image to resize. + /// The current image processing context. /// The target image width. /// The target image height. /// The to perform the resampling. @@ -141,7 +141,7 @@ public static class ResizeExtensions /// The structure that specifies the portion of the target image object to draw to. /// /// Whether to compress and expand the image color-space to gamma correct the image during processing. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize( this IImageProcessingContext source, @@ -166,9 +166,9 @@ public static class ResizeExtensions /// /// Resizes an image in accordance with the given . /// - /// The image to resize. + /// The current image processing context. /// The resize options. - /// The to allow chaining of operations. + /// The . /// Passing zero for one of height or width within the resize options will automatically preserve the aspect ratio of the original image or the nearest possible ratio. public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options) => source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize())); diff --git a/src/ImageSharp/Processing/Extensions/Transforms/RotateExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/RotateExtensions.cs index ac3c464468..fdf28c595f 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/RotateExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/RotateExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Transforms; @@ -14,28 +14,28 @@ public static class RotateExtensions /// /// Rotates and flips an image by the given instructions. /// - /// The image to rotate. + /// The current image processing context. /// The to perform the rotation. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Rotate(this IImageProcessingContext source, RotateMode rotateMode) => Rotate(source, (float)rotateMode); /// /// Rotates an image by the given angle in degrees. /// - /// The image to rotate. + /// The current image processing context. /// The angle in degrees to perform the rotation. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees) => Rotate(source, degrees, KnownResamplers.Bicubic); /// /// Rotates an image by the given angle in degrees using the specified sampling algorithm. /// - /// The image to rotate. + /// The current image processing context. /// The angle in degrees to perform the rotation. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Rotate( this IImageProcessingContext source, float degrees, diff --git a/src/ImageSharp/Processing/Extensions/Transforms/RotateFlipExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/RotateFlipExtensions.cs index fe66af6aa6..4dc324b5ba 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/RotateFlipExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/RotateFlipExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. namespace SixLabors.ImageSharp.Processing; @@ -12,10 +12,10 @@ public static class RotateFlipExtensions /// /// Rotates and flips an image by the given instructions. /// - /// The image to rotate, flip, or both. + /// The current image processing context. /// The to perform the rotation. /// The to perform the flip. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext RotateFlip(this IImageProcessingContext source, RotateMode rotateMode, FlipMode flipMode) => source.Rotate(rotateMode).Flip(flipMode); } diff --git a/src/ImageSharp/Processing/Extensions/Transforms/SkewExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/SkewExtensions.cs index 6b2b8b15f9..09c41b567c 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/SkewExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/SkewExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using SixLabors.ImageSharp.Processing.Processors.Transforms; @@ -14,10 +14,10 @@ public static class SkewExtensions /// /// Skews an image by the given angles in degrees. /// - /// The image to skew. + /// The current image processing context. /// The angle in degrees to perform the skew along the x-axis. /// The angle in degrees to perform the skew along the y-axis. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY) => Skew(source, degreesX, degreesY, KnownResamplers.Bicubic); @@ -25,11 +25,11 @@ public static class SkewExtensions /// /// Skews an image by the given angles in degrees using the specified sampling algorithm. /// - /// The image to skew. + /// The current image processing context. /// The angle in degrees to perform the skew along the x-axis. /// The angle in degrees to perform the skew along the y-axis. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Skew( this IImageProcessingContext source, float degreesX, diff --git a/src/ImageSharp/Processing/Extensions/Transforms/SwizzleExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/SwizzleExtensions.cs index 73ec111c95..4e107a4f0a 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/SwizzleExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/SwizzleExtensions.cs @@ -13,10 +13,10 @@ public static class SwizzleExtensions /// /// Swizzles an image. /// - /// The image to swizzle. + /// The current image processing context. /// The swizzler function. /// The swizzler function type. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Swizzle(this IImageProcessingContext source, TSwizzler swizzler) where TSwizzler : struct, ISwizzler => source.ApplyProcessor(new SwizzleProcessor(swizzler)); diff --git a/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs index fbf3b3a6df..e88f000a7c 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.Numerics; @@ -15,9 +15,9 @@ public static class TransformExtensions /// /// Performs an affine transform of an image. /// - /// The image to transform. + /// The current image processing context. /// The affine transform builder. - /// The + /// The . public static IImageProcessingContext Transform( this IImageProcessingContext source, AffineTransformBuilder builder) => @@ -26,62 +26,60 @@ public static class TransformExtensions /// /// Performs an affine transform of an image using the specified sampling algorithm. /// - /// The . + /// The current image processing context. /// The affine transform builder. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + this IImageProcessingContext source, AffineTransformBuilder builder, IResampler sampler) => - ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); + source.Transform(new Rectangle(Point.Empty, source.GetCurrentSize()), builder, sampler); /// /// Performs an affine transform of an image using the specified sampling algorithm. /// - /// The . + /// The current image processing context. /// The source rectangle /// The affine transform builder. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + this IImageProcessingContext source, Rectangle sourceRectangle, AffineTransformBuilder builder, IResampler sampler) { Matrix3x2 transform = builder.BuildMatrix(sourceRectangle); Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform); - return ctx.Transform(sourceRectangle, transform, targetDimensions, sampler); + return source.Transform(sourceRectangle, transform, targetDimensions, sampler); } /// /// Performs an affine transform of an image using the specified sampling algorithm. /// - /// The . + /// The current image processing context. /// The source rectangle /// The transformation matrix. /// The size of the result image. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + this IImageProcessingContext source, Rectangle sourceRectangle, Matrix3x2 transform, Size targetDimensions, IResampler sampler) - { - return ctx.ApplyProcessor( + => source.ApplyProcessor( new AffineTransformProcessor(transform, sampler, targetDimensions), sourceRectangle); - } /// /// Performs a projective transform of an image. /// - /// The image to transform. + /// The current image processing context. /// The affine transform builder. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Transform( this IImageProcessingContext source, ProjectiveTransformBuilder builder) => @@ -90,53 +88,51 @@ public static class TransformExtensions /// /// Performs a projective transform of an image using the specified sampling algorithm. /// - /// The . + /// The current image processing context. /// The projective transform builder. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + this IImageProcessingContext source, ProjectiveTransformBuilder builder, IResampler sampler) => - ctx.Transform(new Rectangle(Point.Empty, ctx.GetCurrentSize()), builder, sampler); + source.Transform(new Rectangle(Point.Empty, source.GetCurrentSize()), builder, sampler); /// /// Performs a projective transform of an image using the specified sampling algorithm. /// - /// The . + /// The current image processing context. /// The source rectangle /// The projective transform builder. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + this IImageProcessingContext source, Rectangle sourceRectangle, ProjectiveTransformBuilder builder, IResampler sampler) { Matrix4x4 transform = builder.BuildMatrix(sourceRectangle); Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform); - return ctx.Transform(sourceRectangle, transform, targetDimensions, sampler); + return source.Transform(sourceRectangle, transform, targetDimensions, sampler); } /// /// Performs a projective transform of an image using the specified sampling algorithm. /// - /// The . + /// The current image processing context. /// The source rectangle /// The transformation matrix. /// The size of the result image. /// The to perform the resampling. - /// The to allow chaining of operations. + /// The . public static IImageProcessingContext Transform( - this IImageProcessingContext ctx, + this IImageProcessingContext source, Rectangle sourceRectangle, Matrix4x4 transform, Size targetDimensions, IResampler sampler) - { - return ctx.ApplyProcessor( + => source.ApplyProcessor( new ProjectiveTransformProcessor(transform, sampler, targetDimensions), sourceRectangle); - } } From 2964becc21c4dd2ed1c18ba679399edc93ec95ba Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 27 Jan 2023 09:13:54 +1000 Subject: [PATCH 27/37] Increase sleep time for slow VMs --- .../Memory/Allocators/MemoryDiagnosticsTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs b/tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs index 1876d26479..44117f9388 100644 --- a/tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs +++ b/tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Six Labors Split License. using System.Runtime.CompilerServices; @@ -94,7 +94,7 @@ public class MemoryDiagnosticsTests if (subscribeLeakHandle) { // Make sure at least some of the leak callbacks have time to complete on the ThreadPool - Thread.Sleep(200); + Thread.Sleep(500); Assert.True(leakCounter > 3, $"leakCounter did not count enough leaks ({leakCounter} only)"); } From 42eb11046e8554f9b01fa430c8f1f683eb1ed49c Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 28 Jan 2023 11:47:56 +1000 Subject: [PATCH 28/37] Update MemoryDiagnosticsTests.cs --- .../Memory/Allocators/MemoryDiagnosticsTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs b/tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs index 44117f9388..b8dd4be8df 100644 --- a/tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs +++ b/tests/ImageSharp.Tests/Memory/Allocators/MemoryDiagnosticsTests.cs @@ -94,7 +94,7 @@ public class MemoryDiagnosticsTests if (subscribeLeakHandle) { // Make sure at least some of the leak callbacks have time to complete on the ThreadPool - Thread.Sleep(500); + Thread.Sleep(1000); Assert.True(leakCounter > 3, $"leakCounter did not count enough leaks ({leakCounter} only)"); } From cf4c384cc4b732853d18ba24fedd7f93bb351ae3 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 31 Jan 2023 20:04:04 +1000 Subject: [PATCH 29/37] Add test images --- tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs | 3 +++ tests/ImageSharp.Tests/TestImages.cs | 2 ++ tests/Images/Input/Jpg/issues/issue-2334-a.jpg | 3 +++ tests/Images/Input/Jpg/issues/issue-2334-b.jpg | 3 +++ 4 files changed, 11 insertions(+) create mode 100644 tests/Images/Input/Jpg/issues/issue-2334-a.jpg create mode 100644 tests/Images/Input/Jpg/issues/issue-2334-b.jpg diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 425d12497c..80789178d1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -302,8 +302,11 @@ public partial class JpegDecoderTests } // https://github.com/SixLabors/ImageSharp/issues/2315 + // https://github.com/SixLabors/ImageSharp/issues/2334 [Theory] [WithFile(TestImages.Jpeg.Issues.Issue2315_NotEnoughBytes, PixelTypes.Rgba32)] + [WithFile(TestImages.Jpeg.Issues.Issue2334_NotEnoughBytesA, PixelTypes.Rgba32)] + [WithFile(TestImages.Jpeg.Issues.Issue2334_NotEnoughBytesB, PixelTypes.Rgba32)] public void Issue2315_DecodeWorks(TestImageProvider provider) where TPixel : unmanaged, IPixel { diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 22a48ebee4..2de508b75c 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -282,6 +282,8 @@ public static class TestImages public const string Issue2133_DeduceColorSpace = "Jpg/issues/Issue2133.jpg"; public const string Issue2136_ScanMarkerExtraneousBytes = "Jpg/issues/Issue2136-scan-segment-extraneous-bytes.jpg"; public const string Issue2315_NotEnoughBytes = "Jpg/issues/issue-2315.jpg"; + public const string Issue2334_NotEnoughBytesA = "Jpg/issues/issue-2334-a.jpg"; + public const string Issue2334_NotEnoughBytesB = "Jpg/issues/issue-2334-b.jpg"; public static class Fuzz { diff --git a/tests/Images/Input/Jpg/issues/issue-2334-a.jpg b/tests/Images/Input/Jpg/issues/issue-2334-a.jpg new file mode 100644 index 0000000000..8f7ac362d8 --- /dev/null +++ b/tests/Images/Input/Jpg/issues/issue-2334-a.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75d7e645cc359340a0a77f13c842551dce8f82773d2eba18bf18b149dcf9a2ff +size 411155 diff --git a/tests/Images/Input/Jpg/issues/issue-2334-b.jpg b/tests/Images/Input/Jpg/issues/issue-2334-b.jpg new file mode 100644 index 0000000000..edfc9637b8 --- /dev/null +++ b/tests/Images/Input/Jpg/issues/issue-2334-b.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad6725bfa405454f6fb524dd632a53367f8853fd4a68705c773f0aeef068f7b3 +size 159229 From 34add6aebfc0c7d4f5117ab7bbbd6cdf87071b5c Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Tue, 31 Jan 2023 18:00:44 +0100 Subject: [PATCH 30/37] Remove nullable disable from pixelimplementations #2231 --- src/ImageSharp/PixelFormats/PixelImplementations/A8.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Abgr32.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs | 3 +-- .../PixelFormats/PixelImplementations/Bgra4444.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs | 3 +-- .../PixelFormats/PixelImplementations/HalfSingle.cs | 3 +-- .../PixelFormats/PixelImplementations/HalfVector2.cs | 3 +-- .../PixelFormats/PixelImplementations/HalfVector4.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/L16.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/L8.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/La16.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/La32.cs | 3 +-- .../PixelFormats/PixelImplementations/NormalizedByte2.cs | 3 +-- .../PixelFormats/PixelImplementations/NormalizedByte4.cs | 3 +-- .../PixelFormats/PixelImplementations/NormalizedShort2.cs | 3 +-- .../PixelFormats/PixelImplementations/NormalizedShort4.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs | 3 +-- .../PixelFormats/PixelImplementations/Rgba1010102.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs | 7 +++---- src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs | 3 +-- .../PixelFormats/PixelImplementations/RgbaVector.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs | 3 +-- src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs | 3 +-- 28 files changed, 30 insertions(+), 58 deletions(-) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs index 1da5645835..0256907121 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -140,7 +139,7 @@ public partial struct A8 : IPixel, IPackedVector /// /// 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 28b6899b2a..ca68c5aaf9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Abgr32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Abgr32.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -335,7 +334,7 @@ public partial struct Abgr32 : IPixel, IPackedVector } /// - 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 935751afcd..0c99adb52d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -334,7 +333,7 @@ public partial struct Argb32 : IPixel, IPackedVector } /// - 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 751e0bfe86..65b36059b8 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -232,7 +231,7 @@ public partial struct Bgr24 : IPixel 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 21766431cf..ac3b6f8299 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -151,7 +150,7 @@ public partial struct Bgr565 : IPixel, IPackedVector (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 204919392d..6b859cda64 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -287,7 +286,7 @@ public partial struct Bgra32 : IPixel, IPackedVector } /// - 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 e342d18455..8ba32c8ac2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -143,7 +142,7 @@ public partial struct Bgra4444 : IPixel, IPackedVector 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/Byte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs index 9d9b7c87fc..e699e5fe58 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -141,7 +140,7 @@ public partial struct Byte4 : IPixel, IPackedVector 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 a99462c8b9..db1e02adc2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -140,7 +139,7 @@ public partial struct HalfSingle : IPixel, IPackedVector 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 2f2117c26f..9caae58c95 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -157,7 +156,7 @@ public partial struct HalfVector2 : IPixel, IPackedVector } /// - 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 859ba7e320..609fec3bd7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -149,7 +148,7 @@ public partial struct HalfVector4 : IPixel, IPackedVector 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 5d2539ce13..c6ee8744d9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -153,7 +152,7 @@ public partial struct L16 : IPixel, IPackedVector 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 25a79e58fc..383e09b270 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -143,7 +142,7 @@ public partial struct L8 : IPixel, IPackedVector 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 21e66ed495..7597677a26 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -80,7 +79,7 @@ public partial struct La16 : IPixel, IPackedVector 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 cf53d2217b..cb8fad228d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -82,7 +81,7 @@ public partial struct La32 : IPixel, IPackedVector 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 d9d0a53bd8..92b9e6148a 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -162,7 +161,7 @@ public partial struct NormalizedByte2 : IPixel, IPackedVector> 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 5a18d00a2d..f87bb5a602 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -154,7 +153,7 @@ public partial struct NormalizedByte4 : IPixel, IPackedVector 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 84e5e43625..f77dd69b71 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -163,7 +162,7 @@ public partial struct NormalizedShort2 : IPixel, IPackedVector (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 f8139c547b..989edbd2ba 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -155,7 +154,7 @@ public partial struct NormalizedShort4 : IPixel, IPackedVector 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 69f39c8838..0a13a15eda 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -146,7 +145,7 @@ public partial struct Rg32 : IPixel, IPackedVector 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 5f66341571..105618cd96 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -241,7 +240,7 @@ public partial struct Rgb24 : IPixel } /// - 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 16673fca2f..1cf63eb24c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -210,7 +209,7 @@ public partial struct Rgb48 : IPixel 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 2c59741bf4..7bac1d9208 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -141,7 +140,7 @@ public partial struct Rgba1010102 : IPixel, IPackedVector 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 0d18ac3431..a652c2b339 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers.Binary; using System.Globalization; @@ -267,7 +266,7 @@ public partial struct Rgba32 : IPixel, IPackedVector /// 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)) @@ -437,7 +436,7 @@ public partial struct Rgba32 : IPixel, IPackedVector } /// - 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)] @@ -514,7 +513,7 @@ public partial struct Rgba32 : IPixel, IPackedVector /// /// 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 7560892120..81c9591480 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -444,7 +443,7 @@ public partial struct Rgba64 : IPixel, IPackedVector } /// - 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 3a0426a8e1..899987b712 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Globalization; using System.Numerics; @@ -193,7 +192,7 @@ public partial struct RgbaVector : IPixel } /// - 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 8eb33afd35..832e8c770f 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -164,7 +163,7 @@ public partial struct Short2 : IPixel, IPackedVector 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 b964c9ec50..c4dc324a13 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -164,7 +163,7 @@ public partial struct Short4 : IPixel, IPackedVector 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)] From 8504518073a46b8a0fdc1a7c86377c3ef4b80593 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Tue, 31 Jan 2023 18:50:23 +0100 Subject: [PATCH 31/37] Remove nullable disable from Processing.Processors #2231 --- .../DefaultImageProcessorContext{TPixel}.cs | 7 +++-- .../Convolution/KernelSamplingMap.cs | 9 +++---- .../Processors/Drawing/DrawImageProcessor.cs | 5 ++-- .../Quantization/OctreeQuantizer{TPixel}.cs | 26 +++++++++---------- .../Quantization/PaletteQuantizer{TPixel}.cs | 4 +-- .../Quantization/QuantizerOptions.cs | 2 +- .../Quantization/QuantizerUtilities.cs | 2 +- .../Quantization/WuQuantizer{TPixel}.cs | 10 +++---- .../AffineTransformProcessor{TPixel}.cs | 9 +++---- .../ProjectiveTransformProcessor{TPixel}.cs | 9 +++---- .../Resize/ResizeProcessor{TPixel}.cs | 5 ++-- 11 files changed, 39 insertions(+), 49 deletions(-) diff --git a/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs b/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs index 208455b902..4d95e060dc 100644 --- a/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs +++ b/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Collections.Concurrent; using SixLabors.ImageSharp.PixelFormats; @@ -17,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. @@ -54,7 +53,7 @@ internal class DefaultImageProcessorContext : IInternalImageProcessingCo this.destination = this.source.Clone(); } - return this.destination; + return this.destination!; } /// @@ -87,7 +86,7 @@ internal class DefaultImageProcessorContext : IInternalImageProcessingCo } // 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/Processors/Convolution/KernelSamplingMap.cs b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs index 4cae2f858e..8128d01196 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Runtime.CompilerServices; @@ -16,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. @@ -65,10 +64,10 @@ internal sealed class KernelSamplingMap : IDisposable } [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/Drawing/DrawImageProcessor.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs index 9de4f862b8..88b59b7dc6 100644 --- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; @@ -65,7 +64,7 @@ public class DrawImageProcessor : IImageProcessor { ProcessorFactoryVisitor visitor = new(configuration, this, source, sourceRectangle); this.Image.AcceptVisitor(visitor); - return visitor.Result; + return visitor.Result!; } private class ProcessorFactoryVisitor : IImageVisitor @@ -84,7 +83,7 @@ public class DrawImageProcessor : IImageProcessor 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/Quantization/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs index 43d11777db..61ffcc6ccd 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Diagnostics.CodeAnalysis; @@ -27,9 +26,10 @@ public struct OctreeQuantizer : IQuantizer private readonly int maxColors; private readonly int bitDepth; private readonly Octree octree; - private IMemoryOwner paletteOwner; + [NotNull] + private IMemoryOwner? paletteOwner; private ReadOnlyMemory palette; - private EuclideanPixelMap pixelMap; + private EuclideanPixelMap? pixelMap; private readonly bool isDithering; private bool isDisposed; @@ -143,7 +143,7 @@ public struct OctreeQuantizer : IQuantizer // 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); @@ -183,7 +183,7 @@ public struct OctreeQuantizer : IQuantizer /// /// Store the last node quantized /// - private OctreeNode previousNode; + private OctreeNode? previousNode; /// /// Cache the previous color quantized @@ -221,7 +221,7 @@ public struct OctreeQuantizer : IQuantizer /// /// Gets the array of reducible nodes /// - private OctreeNode[] ReducibleNodes + private OctreeNode?[] ReducibleNodes { [MethodImpl(InliningOptions.ShortMethod)] get; @@ -311,7 +311,7 @@ public struct OctreeQuantizer : IQuantizer } // Reduce the node most recently added to the list at level 'index' - OctreeNode node = this.ReducibleNodes[index]; + OctreeNode node = this.ReducibleNodes[index]!; this.ReducibleNodes[index] = node.NextReducible; // Decrement the leaf count after reducing the node @@ -330,7 +330,7 @@ public struct OctreeQuantizer : IQuantizer /// /// Pointers to any child nodes /// - private readonly OctreeNode[] children; + private readonly OctreeNode?[]? children; /// /// Flag indicating that this is a leaf node @@ -395,7 +395,7 @@ public struct OctreeQuantizer : IQuantizer /// /// Gets the next reducible node /// - public OctreeNode NextReducible + public OctreeNode? NextReducible { [MethodImpl(InliningOptions.ShortMethod)] get; @@ -423,7 +423,7 @@ public struct OctreeQuantizer : IQuantizer // 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 @@ -448,7 +448,7 @@ public struct OctreeQuantizer : IQuantizer // 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; @@ -495,7 +495,7 @@ public struct OctreeQuantizer : IQuantizer // 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); } } } @@ -517,7 +517,7 @@ public struct OctreeQuantizer : IQuantizer } 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 7b351a61f5..f8f9658a85 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -21,7 +20,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization; internal struct PaletteQuantizer : IQuantizer where TPixel : unmanaged, IPixel { - private EuclideanPixelMap pixelMap; + [NotNull] + private EuclideanPixelMap? pixelMap; /// /// Initializes a new instance of the struct. diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs index f52cfd6ea7..b3d03d9338 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs @@ -17,7 +17,7 @@ public class QuantizerOptions /// Gets or sets the algorithm to apply to the output image. /// Defaults to ; set to for no dithering. /// - public IDither Dither { get; set; } = QuantizerConstants.DefaultDither; + public IDither? Dither { get; set; } = QuantizerConstants.DefaultDither; /// /// Gets or sets the dithering scale used to adjust the amount of dither. Range 0..1. diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs index 167cf91282..53203f94a0 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs @@ -146,7 +146,7 @@ public static class QuantizerUtilities where TFrameQuantizer : struct, IQuantizer where TPixel : unmanaged, IPixel { - IDither dither = quantizer.Options.Dither; + IDither? dither = quantizer.Options.Dither; 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 e0aede058a..0119558bff 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Buffers; using System.Diagnostics.CodeAnalysis; @@ -76,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; @@ -175,7 +174,7 @@ internal struct WuQuantizer : IQuantizer { if (this.isDithering) { - return (byte)this.pixelMap.GetClosestColor(color, out match); + return (byte)this.pixelMap!.GetClosestColor(color, out match); } Rgba32 rgba = default; @@ -203,9 +202,6 @@ internal struct WuQuantizer : IQuantizer this.momentsOwner?.Dispose(); this.tagsOwner?.Dispose(); this.paletteOwner?.Dispose(); - this.momentsOwner = null; - this.tagsOwner = null; - this.paletteOwner = null; this.pixelMap?.Dispose(); this.pixelMap = null; } @@ -869,7 +865,7 @@ internal struct WuQuantizer : IQuantizer 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/Linear/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs index b9ff551691..c5c2a778eb 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -20,8 +19,8 @@ internal class AffineTransformProcessor : 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. @@ -53,8 +52,8 @@ internal class AffineTransformProcessor : TransformProcessor, IR 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. diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs index 7d1a10926c..b741dc4ee6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Numerics; using System.Runtime.CompilerServices; @@ -20,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. @@ -53,8 +52,8 @@ internal class ProjectiveTransformProcessor : TransformProcessor 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. diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index ba96e76ae0..98c2523fae 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -1,6 +1,5 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -#nullable disable using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; @@ -21,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) @@ -56,7 +55,7 @@ internal class ResizeProcessor : TransformProcessor, IResampling { 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; From e7bcc5f13270ce8eed50f8df73274f7a67a2c789 Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Tue, 31 Jan 2023 18:58:49 +0100 Subject: [PATCH 32/37] Fix build Code analysis in rider did not catch that. only the build failed. --- .../Processors/Quantization/OctreeQuantizer{TPixel}.cs | 5 ++--- .../Processors/Quantization/PaletteQuantizer{TPixel}.cs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs index 61ffcc6ccd..83e0a8b08f 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs @@ -26,7 +26,6 @@ public struct OctreeQuantizer : IQuantizer private readonly int maxColors; private readonly int bitDepth; private readonly Octree octree; - [NotNull] private IMemoryOwner? paletteOwner; private ReadOnlyMemory palette; private EuclideanPixelMap? pixelMap; @@ -99,7 +98,7 @@ public struct OctreeQuantizer : IQuantizer } int paletteIndex = 0; - Span paletteSpan = this.paletteOwner.GetSpan(); + Span paletteSpan = this.paletteOwner!.GetSpan(); // On very rare occasions, (blur.png), the quantizer does not preserve a // transparent entry when palletizing the captured colors. @@ -113,7 +112,7 @@ public struct OctreeQuantizer : IQuantizer } this.octree.Palletize(paletteSpan, max, ref paletteIndex); - ReadOnlyMemory result = this.paletteOwner.Memory[..paletteSpan.Length]; + ReadOnlyMemory result = this.paletteOwner!.Memory[..paletteSpan.Length]; // When called multiple times by QuantizerUtilities.BuildPalette // this prevents memory churn caused by reallocation. diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs index f8f9658a85..e73c87896f 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs @@ -20,7 +20,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization; internal struct PaletteQuantizer : IQuantizer where TPixel : unmanaged, IPixel { - [NotNull] private EuclideanPixelMap? pixelMap; /// @@ -47,7 +46,7 @@ internal struct PaletteQuantizer : IQuantizer public QuantizerOptions Options { get; } /// - public ReadOnlyMemory Palette => this.pixelMap.Palette; + public ReadOnlyMemory Palette => this.pixelMap!.Palette; /// [MethodImpl(InliningOptions.ShortMethod)] @@ -63,7 +62,7 @@ internal struct PaletteQuantizer : IQuantizer /// [MethodImpl(InliningOptions.ShortMethod)] public readonly byte GetQuantizedColor(TPixel color, out TPixel match) - => (byte)this.pixelMap.GetClosestColor(color, out match); + => (byte)this.pixelMap!.GetClosestColor(color, out match); /// public void Dispose() From 7847fab011b2608f593d8e51b553824ec3a7e4af Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 1 Feb 2023 06:57:50 +0100 Subject: [PATCH 33/37] Remove ? for pixelMap and paletteOwner --- .../Processors/Quantization/OctreeQuantizer{TPixel}.cs | 9 ++++----- .../Processors/Quantization/PaletteQuantizer{TPixel}.cs | 9 ++++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs index 83e0a8b08f..d66a38d80d 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs @@ -26,7 +26,7 @@ public struct OctreeQuantizer : IQuantizer private readonly int maxColors; private readonly int bitDepth; private readonly Octree octree; - private IMemoryOwner? paletteOwner; + private IMemoryOwner paletteOwner; private ReadOnlyMemory palette; private EuclideanPixelMap? pixelMap; private readonly bool isDithering; @@ -98,7 +98,7 @@ public struct OctreeQuantizer : IQuantizer } int paletteIndex = 0; - Span paletteSpan = this.paletteOwner!.GetSpan(); + Span paletteSpan = this.paletteOwner.GetSpan(); // On very rare occasions, (blur.png), the quantizer does not preserve a // transparent entry when palletizing the captured colors. @@ -112,7 +112,7 @@ public struct OctreeQuantizer : IQuantizer } this.octree.Palletize(paletteSpan, max, ref paletteIndex); - ReadOnlyMemory result = this.paletteOwner!.Memory[..paletteSpan.Length]; + ReadOnlyMemory result = this.paletteOwner.Memory[..paletteSpan.Length]; // When called multiple times by QuantizerUtilities.BuildPalette // this prevents memory churn caused by reallocation. @@ -157,8 +157,7 @@ public struct OctreeQuantizer : IQuantizer if (!this.isDisposed) { this.isDisposed = true; - this.paletteOwner?.Dispose(); - this.paletteOwner = null; + this.paletteOwner.Dispose(); this.pixelMap?.Dispose(); this.pixelMap = null; } diff --git a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs index e73c87896f..ea7413aab4 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/PaletteQuantizer{TPixel}.cs @@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization; internal struct PaletteQuantizer : IQuantizer where TPixel : unmanaged, IPixel { - private EuclideanPixelMap? pixelMap; + private EuclideanPixelMap pixelMap; /// /// Initializes a new instance of the struct. @@ -46,7 +46,7 @@ internal struct PaletteQuantizer : IQuantizer public QuantizerOptions Options { get; } /// - public ReadOnlyMemory Palette => this.pixelMap!.Palette; + public ReadOnlyMemory Palette => this.pixelMap.Palette; /// [MethodImpl(InliningOptions.ShortMethod)] @@ -62,12 +62,11 @@ internal struct PaletteQuantizer : IQuantizer /// [MethodImpl(InliningOptions.ShortMethod)] public readonly byte GetQuantizedColor(TPixel color, out TPixel match) - => (byte)this.pixelMap!.GetClosestColor(color, out match); + => (byte)this.pixelMap.GetClosestColor(color, out match); /// public void Dispose() { - this.pixelMap?.Dispose(); - this.pixelMap = null; + this.pixelMap.Dispose(); } } From df803cd34de6284835f751419dd9d2be471431df Mon Sep 17 00:00:00 2001 From: Stefan Nikolei Date: Wed, 1 Feb 2023 07:39:36 +0100 Subject: [PATCH 34/37] Fix nullref the quantizier was initialized with default --> all properties are null. So we need to check that --- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 9cc045d45e..eaa6852937 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -171,7 +171,10 @@ internal sealed class GifEncoderCore : IImageEncoderInternals quantized = null; } - paletteQuantizer.Dispose(); + if (hasPaletteQuantizer) + { + paletteQuantizer.Dispose(); + } } private void EncodeFrame( From a1a2cec28463e6c10e40c5f27e7d35db989d41bd Mon Sep 17 00:00:00 2001 From: Petar Tasev Date: Wed, 1 Feb 2023 00:45:09 -0800 Subject: [PATCH 35/37] Added L16 support to tiff encoder (unit tests WIP) --- .../Tiff/Compression/HorizontalPredictor.cs | 31 ++++++++++++ .../Formats/Tiff/Constants/TiffConstants.cs | 5 ++ .../Formats/Tiff/TiffBitsPerPixel.cs | 2 +- .../Formats/Tiff/TiffEncoderCore.cs | 20 +++++++- .../Tiff/TiffEncoderEntriesCollector.cs | 20 ++++---- .../Tiff/Writers/TiffColorWriterFactory.cs | 9 ++-- .../Tiff/Writers/TiffGrayL16Writer{TPixel}.cs | 22 +++++++++ .../Formats/Tiff/TiffEncoderTests.cs | 47 +++++++++++++++++-- 8 files changed, 136 insertions(+), 20 deletions(-) create mode 100644 src/ImageSharp/Formats/Tiff/Writers/TiffGrayL16Writer{TPixel}.cs diff --git a/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs b/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs index be1d00e7ed..9a4e4ba2b9 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/HorizontalPredictor.cs @@ -67,6 +67,11 @@ internal static class HorizontalPredictor { ApplyHorizontalPrediction8Bit(rows, width); } + else if (bitsPerPixel == 16) + { + // Assume rows are L16 grayscale since that's currently the only way 16 bits is supported by encoder + ApplyHorizontalPrediction16Bit(rows, width); + } else if (bitsPerPixel == 24) { ApplyHorizontalPrediction24Bit(rows, width); @@ -102,6 +107,32 @@ internal static class HorizontalPredictor } } + /// + /// Applies a horizontal predictor to the L16 row. + /// Make use of the fact that many continuous-tone images rarely vary much in pixel value from one pixel to the next. + /// In such images, if we replace the pixel values by differences between consecutive pixels, many of the differences should be 0, plus + /// or minus 1, and so on.This reduces the apparent information content and allows LZW to encode the data more compactly. + /// + /// The L16 pixel rows. + /// The width. + [MethodImpl(InliningOptions.ShortMethod)] + private static void ApplyHorizontalPrediction16Bit(Span rows, int width) + { + DebugGuard.IsTrue(rows.Length % width == 0, "Values must be equals"); + int height = rows.Length / width; + for (int y = 0; y < height; y++) + { + Span rowSpan = rows.Slice(y * width, width); + Span rowL16 = MemoryMarshal.Cast(rowSpan); + + for (int x = rowL16.Length - 1; x >= 1; x--) + { + ushort val = (ushort)(rowL16[x].PackedValue - rowL16[x - 1].PackedValue); + rowL16[x].PackedValue = val; + } + } + } + /// /// Applies a horizontal predictor to a gray pixel row. /// diff --git a/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs b/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs index 05dacfef65..978860910c 100644 --- a/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs +++ b/src/ImageSharp/Formats/Tiff/Constants/TiffConstants.cs @@ -73,6 +73,11 @@ internal static class TiffConstants /// public static readonly TiffBitsPerSample BitsPerSample8Bit = new TiffBitsPerSample(8, 0, 0); + /// + /// The bits per sample for 16-bit grayscale images. + /// + public static readonly TiffBitsPerSample BitsPerSample16Bit = new TiffBitsPerSample(16, 0, 0); + /// /// The bits per sample for color images with 8 bits for each color channel. /// diff --git a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs index bcc249bbec..38da4b5f8b 100644 --- a/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs +++ b/src/ImageSharp/Formats/Tiff/TiffBitsPerPixel.cs @@ -54,7 +54,7 @@ public enum TiffBitsPerPixel /// /// 16 bits per pixel, for gray images. /// - /// Note: The TiffEncoder does not yet support 16 bits per color channel and will default to 24 bits per pixel instead. + /// Note: The TiffEncoder does not yet support 16 bits per color channel and will default to 16 bits grayscale instead. /// Bit16 = 16, diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs index 3a4e71d3e8..94c7fb2b1e 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs @@ -376,11 +376,14 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals case TiffBitsPerPixel.Bit8: this.SetEncoderOptions(bitsPerPixel, photometricInterpretation ?? TiffPhotometricInterpretation.BlackIsZero, compression, predictor); break; + case TiffBitsPerPixel.Bit16: + // Assume desire to encode as L16 grayscale + this.SetEncoderOptions(bitsPerPixel, TiffPhotometricInterpretation.BlackIsZero, compression, predictor); + break; case TiffBitsPerPixel.Bit6: case TiffBitsPerPixel.Bit10: case TiffBitsPerPixel.Bit12: case TiffBitsPerPixel.Bit14: - case TiffBitsPerPixel.Bit16: case TiffBitsPerPixel.Bit30: case TiffBitsPerPixel.Bit36: case TiffBitsPerPixel.Bit42: @@ -413,13 +416,20 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals return; } - // At the moment only 8 and 32 bits per pixel can be preserved by the tiff encoder. + // At the moment only 8, 16 and 32 bits per pixel can be preserved by the tiff encoder. if (inputBitsPerPixel == 8) { this.SetEncoderOptions(TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.BlackIsZero, compression, predictor); return; } + if (inputBitsPerPixel == 16) + { + // Assume desire to encode as L16 grayscale + this.SetEncoderOptions(TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, compression, predictor); + return; + } + this.SetEncoderOptions(TiffBitsPerPixel.Bit24, TiffPhotometricInterpretation.Rgb, compression, predictor); return; } @@ -434,6 +444,12 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals return; } + if (inputBitsPerPixel == 16) + { + this.SetEncoderOptions(TiffBitsPerPixel.Bit16, photometricInterpretation, compression, predictor); + return; + } + this.SetEncoderOptions(TiffBitsPerPixel.Bit8, photometricInterpretation, compression, predictor); return; diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs index 7dd073936f..cf9b4ae213 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs @@ -343,20 +343,20 @@ internal class TiffEncoderEntriesCollector return TiffConstants.BitsPerSampleRgb8Bit.ToArray(); case TiffPhotometricInterpretation.WhiteIsZero: - if (encoder.BitsPerPixel == TiffBitsPerPixel.Bit1) + return encoder.BitsPerPixel switch { - return TiffConstants.BitsPerSample1Bit.ToArray(); - } - - return TiffConstants.BitsPerSample8Bit.ToArray(); + TiffBitsPerPixel.Bit1 => TiffConstants.BitsPerSample1Bit.ToArray(), + TiffBitsPerPixel.Bit16 => TiffConstants.BitsPerSample16Bit.ToArray(), + _ => TiffConstants.BitsPerSample8Bit.ToArray() + }; case TiffPhotometricInterpretation.BlackIsZero: - if (encoder.BitsPerPixel == TiffBitsPerPixel.Bit1) + return encoder.BitsPerPixel switch { - return TiffConstants.BitsPerSample1Bit.ToArray(); - } - - return TiffConstants.BitsPerSample8Bit.ToArray(); + TiffBitsPerPixel.Bit1 => TiffConstants.BitsPerSample1Bit.ToArray(), + TiffBitsPerPixel.Bit16 => TiffConstants.BitsPerSample16Bit.ToArray(), + _ => TiffConstants.BitsPerSample8Bit.ToArray() + }; default: return TiffConstants.BitsPerSampleRgb8Bit.ToArray(); diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs index a52d49a353..96c8aeb324 100644 --- a/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffColorWriterFactory.cs @@ -27,12 +27,13 @@ internal static class TiffColorWriterFactory return new TiffPaletteWriter(image, quantizer, pixelSamplingStrategy, memoryAllocator, configuration, entriesCollector, bitsPerPixel); case TiffPhotometricInterpretation.BlackIsZero: case TiffPhotometricInterpretation.WhiteIsZero: - if (bitsPerPixel == 1) + return bitsPerPixel switch { - return new TiffBiColorWriter(image, memoryAllocator, configuration, entriesCollector); - } + 1 => new TiffBiColorWriter(image, memoryAllocator, configuration, entriesCollector), + 16 => new TiffGrayL16Writer(image, memoryAllocator, configuration, entriesCollector), + _ => new TiffGrayWriter(image, memoryAllocator, configuration, entriesCollector) + }; - return new TiffGrayWriter(image, memoryAllocator, configuration, entriesCollector); default: return new TiffRgbWriter(image, memoryAllocator, configuration, entriesCollector); } diff --git a/src/ImageSharp/Formats/Tiff/Writers/TiffGrayL16Writer{TPixel}.cs b/src/ImageSharp/Formats/Tiff/Writers/TiffGrayL16Writer{TPixel}.cs new file mode 100644 index 0000000000..3e0e074e95 --- /dev/null +++ b/src/ImageSharp/Formats/Tiff/Writers/TiffGrayL16Writer{TPixel}.cs @@ -0,0 +1,22 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Formats.Tiff.Writers; + +internal sealed class TiffGrayL16Writer : TiffCompositeColorWriter + where TPixel : unmanaged, IPixel +{ + public TiffGrayL16Writer(ImageFrame image, MemoryAllocator memoryAllocator, Configuration configuration, TiffEncoderEntriesCollector entriesCollector) + : base(image, memoryAllocator, configuration, entriesCollector) + { + } + + /// + public override int BitsPerPixel => 16; + + /// + protected override void EncodePixels(Span pixels, Span buffer) => PixelOperations.Instance.ToL16Bytes(this.Configuration, pixels, buffer, pixels.Length); +} diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs index 97445ad6cf..bae429e65a 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs @@ -17,6 +17,7 @@ public class TiffEncoderTests : TiffEncoderBaseTester [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffBitsPerPixel.Bit8)] [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffBitsPerPixel.Bit8)] [InlineData(TiffPhotometricInterpretation.WhiteIsZero, TiffBitsPerPixel.Bit8)] + [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffBitsPerPixel.Bit16)] //// Unsupported TiffPhotometricInterpretation should default to 24 bits [InlineData(TiffPhotometricInterpretation.CieLab, TiffBitsPerPixel.Bit24)] [InlineData(TiffPhotometricInterpretation.ColorFilterArray, TiffBitsPerPixel.Bit24)] @@ -28,7 +29,9 @@ public class TiffEncoderTests : TiffEncoderBaseTester { // arrange var tiffEncoder = new TiffEncoder { PhotometricInterpretation = photometricInterpretation }; - using Image input = new Image(10, 10); + using Image input = expectedBitsPerPixel is TiffBitsPerPixel.Bit16 + ? new Image(10, 10) + : new Image(10, 10); using var memStream = new MemoryStream(); // act @@ -44,6 +47,7 @@ public class TiffEncoderTests : TiffEncoderBaseTester [Theory] [InlineData(TiffBitsPerPixel.Bit24)] + [InlineData(TiffBitsPerPixel.Bit16)] [InlineData(TiffBitsPerPixel.Bit8)] [InlineData(TiffBitsPerPixel.Bit4)] [InlineData(TiffBitsPerPixel.Bit1)] @@ -117,14 +121,17 @@ public class TiffEncoderTests : TiffEncoderBaseTester [Theory] [InlineData(null, TiffCompression.Deflate, TiffBitsPerPixel.Bit24, TiffCompression.Deflate)] [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.Deflate, TiffBitsPerPixel.Bit24, TiffCompression.Deflate)] + [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate, TiffBitsPerPixel.Bit16, TiffCompression.Deflate)] [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate, TiffBitsPerPixel.Bit8, TiffCompression.Deflate)] [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.Deflate, TiffBitsPerPixel.Bit8, TiffCompression.Deflate)] [InlineData(null, TiffCompression.PackBits, TiffBitsPerPixel.Bit24, TiffCompression.PackBits)] [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.PackBits, TiffBitsPerPixel.Bit24, TiffCompression.PackBits)] - [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.PackBits, TiffBitsPerPixel.Bit8, TiffCompression.PackBits)] + [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits, TiffBitsPerPixel.Bit16, TiffCompression.PackBits)] [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits, TiffBitsPerPixel.Bit8, TiffCompression.PackBits)] + [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.PackBits, TiffBitsPerPixel.Bit8, TiffCompression.PackBits)] [InlineData(null, TiffCompression.Lzw, TiffBitsPerPixel.Bit24, TiffCompression.Lzw)] [InlineData(TiffPhotometricInterpretation.Rgb, TiffCompression.Lzw, TiffBitsPerPixel.Bit24, TiffCompression.Lzw)] + [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw, TiffBitsPerPixel.Bit16, TiffCompression.Lzw)] [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw, TiffBitsPerPixel.Bit8, TiffCompression.Lzw)] [InlineData(TiffPhotometricInterpretation.PaletteColor, TiffCompression.Lzw, TiffBitsPerPixel.Bit8, TiffCompression.Lzw)] [InlineData(TiffPhotometricInterpretation.BlackIsZero, TiffCompression.CcittGroup3Fax, TiffBitsPerPixel.Bit1, TiffCompression.CcittGroup3Fax)] @@ -143,7 +150,9 @@ public class TiffEncoderTests : TiffEncoderBaseTester { // arrange var tiffEncoder = new TiffEncoder { PhotometricInterpretation = photometricInterpretation, Compression = compression }; - using Image input = new Image(10, 10); + using Image input = expectedBitsPerPixel is TiffBitsPerPixel.Bit16 + ? new Image(10, 10) + : new Image(10, 10); using var memStream = new MemoryStream(); // act @@ -160,6 +169,7 @@ public class TiffEncoderTests : TiffEncoderBaseTester [Theory] [WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Bit1)] [WithFile(GrayscaleUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Bit8)] + [WithFile(GrayscaleUncompressed, PixelTypes.L16, TiffBitsPerPixel.Bit16)] [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Bit24)] [WithFile(Rgb4BitPalette, PixelTypes.Rgba32, TiffBitsPerPixel.Bit4)] [WithFile(RgbPalette, PixelTypes.Rgba32, TiffBitsPerPixel.Bit8)] @@ -406,6 +416,36 @@ public class TiffEncoderTests : TiffEncoderBaseTester where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.PaletteColor, TiffCompression.Lzw, TiffPredictor.Horizontal, useExactComparer: false, compareTolerance: 0.001f); + [Theory] + [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + public void TiffEncoder_EncodeGray16_Works(TestImageProvider provider) + where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero); + + [Theory] + [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + public void TiffEncoder_EncodeGray16_WithDeflateCompression_Works(TestImageProvider provider) + where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate); + + [Theory] + [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + public void TiffEncoder_EncodeGray16_WithDeflateCompressionAndPredictor_Works(TestImageProvider provider) + where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate, TiffPredictor.Horizontal); + + [Theory] + [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + public void TiffEncoder_EncodeGray16_WithLzwCompression_Works(TestImageProvider provider) + where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw); + + [Theory] + [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + public void TiffEncoder_EncodeGray16_WithLzwCompressionAndPredictor_Works(TestImageProvider provider) + where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw, TiffPredictor.Horizontal); + + [Theory] + [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + public void TiffEncoder_EncodeGray16_WithPackBitsCompression_Works(TestImageProvider provider) + where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits); + [Theory] [WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)] public void TiffEncoder_EncodeBiColor_BlackIsZero_Works(TestImageProvider provider) @@ -473,6 +513,7 @@ public class TiffEncoderTests : TiffEncoderBaseTester [Theory] [WithFile(GrayscaleUncompressed, PixelTypes.L8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits)] + [WithFile(GrayscaleUncompressed, PixelTypes.L16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits)] [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffPhotometricInterpretation.Rgb, TiffCompression.Deflate)] [WithFile(RgbUncompressed, PixelTypes.Rgb24, TiffPhotometricInterpretation.Rgb, TiffCompression.None)] [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffPhotometricInterpretation.Rgb, TiffCompression.None)] From bd9e1ee5080c3527f053a99b8ce4b70def697819 Mon Sep 17 00:00:00 2001 From: Petar Tasev Date: Wed, 1 Feb 2023 21:46:12 -0800 Subject: [PATCH 36/37] Added unit tests and 16 bit grayscale images --- .../Formats/Tiff/TiffDecoderTests.cs | 2 ++ .../Formats/Tiff/TiffEncoderTests.cs | 16 ++++++++-------- .../Formats/Tiff/TiffMetadataTests.cs | 1 + tests/ImageSharp.Tests/TestImages.cs | 2 ++ .../Calliphora_grayscale_uncompressed_16bit.tiff | 3 +++ .../Input/Tiff/grayscale_uncompressed_16bit.tiff | 3 +++ 6 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 tests/Images/Input/Tiff/Calliphora_grayscale_uncompressed_16bit.tiff create mode 100644 tests/Images/Input/Tiff/grayscale_uncompressed_16bit.tiff diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index 8c43fd81d8..31b9ffb318 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs @@ -27,6 +27,7 @@ public class TiffDecoderTests : TiffDecoderBaseTester [InlineData(RgbUncompressed, 24, 256, 256, 300, 300, PixelResolutionUnit.PixelsPerInch)] [InlineData(SmallRgbDeflate, 24, 32, 32, 96, 96, PixelResolutionUnit.PixelsPerInch)] [InlineData(Calliphora_GrayscaleUncompressed, 8, 200, 298, 96, 96, PixelResolutionUnit.PixelsPerInch)] + [InlineData(Calliphora_GrayscaleUncompressed16Bit, 16, 200, 298, 96, 96, PixelResolutionUnit.PixelsPerInch)] [InlineData(Flower4BitPalette, 4, 73, 43, 72, 72, PixelResolutionUnit.PixelsPerInch)] public void Identify(string imagePath, int expectedPixelSize, int expectedWidth, int expectedHeight, double expectedHResolution, double expectedVResolution, PixelResolutionUnit expectedResolutionUnit) { @@ -64,6 +65,7 @@ public class TiffDecoderTests : TiffDecoderBaseTester [Theory] [WithFile(RgbUncompressed, PixelTypes.Rgba32)] [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleUncompressed16Bit, PixelTypes.Rgba32)] [WithFile(Calliphora_RgbUncompressed, PixelTypes.Rgba32)] [WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32)] public void TiffDecoder_CanDecode_Uncompressed(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs index bae429e65a..f8aa1551fc 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderTests.cs @@ -169,7 +169,7 @@ public class TiffEncoderTests : TiffEncoderBaseTester [Theory] [WithFile(Calliphora_BiColorUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Bit1)] [WithFile(GrayscaleUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Bit8)] - [WithFile(GrayscaleUncompressed, PixelTypes.L16, TiffBitsPerPixel.Bit16)] + [WithFile(GrayscaleUncompressed16Bit, PixelTypes.L16, TiffBitsPerPixel.Bit16)] [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffBitsPerPixel.Bit24)] [WithFile(Rgb4BitPalette, PixelTypes.Rgba32, TiffBitsPerPixel.Bit4)] [WithFile(RgbPalette, PixelTypes.Rgba32, TiffBitsPerPixel.Bit8)] @@ -417,32 +417,32 @@ public class TiffEncoderTests : TiffEncoderBaseTester TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit8, TiffPhotometricInterpretation.PaletteColor, TiffCompression.Lzw, TiffPredictor.Horizontal, useExactComparer: false, compareTolerance: 0.001f); [Theory] - [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleUncompressed16Bit, PixelTypes.Rgba32)] public void TiffEncoder_EncodeGray16_Works(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero); [Theory] - [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleUncompressed16Bit, PixelTypes.Rgba32)] public void TiffEncoder_EncodeGray16_WithDeflateCompression_Works(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate); [Theory] - [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleUncompressed16Bit, PixelTypes.Rgba32)] public void TiffEncoder_EncodeGray16_WithDeflateCompressionAndPredictor_Works(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Deflate, TiffPredictor.Horizontal); [Theory] - [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleUncompressed16Bit, PixelTypes.Rgba32)] public void TiffEncoder_EncodeGray16_WithLzwCompression_Works(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw); [Theory] - [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleUncompressed16Bit, PixelTypes.Rgba32)] public void TiffEncoder_EncodeGray16_WithLzwCompressionAndPredictor_Works(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.Lzw, TiffPredictor.Horizontal); [Theory] - [WithFile(Calliphora_GrayscaleUncompressed, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleUncompressed16Bit, PixelTypes.Rgba32)] public void TiffEncoder_EncodeGray16_WithPackBitsCompression_Works(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffEncoderCore(provider, TiffBitsPerPixel.Bit16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits); @@ -513,7 +513,7 @@ public class TiffEncoderTests : TiffEncoderBaseTester [Theory] [WithFile(GrayscaleUncompressed, PixelTypes.L8, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits)] - [WithFile(GrayscaleUncompressed, PixelTypes.L16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits)] + [WithFile(GrayscaleUncompressed16Bit, PixelTypes.L16, TiffPhotometricInterpretation.BlackIsZero, TiffCompression.PackBits)] [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffPhotometricInterpretation.Rgb, TiffCompression.Deflate)] [WithFile(RgbUncompressed, PixelTypes.Rgb24, TiffPhotometricInterpretation.Rgb, TiffCompression.None)] [WithFile(RgbUncompressed, PixelTypes.Rgba32, TiffPhotometricInterpretation.Rgb, TiffCompression.None)] diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs index 51c0b6ef7e..5b09a244b5 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffMetadataTests.cs @@ -75,6 +75,7 @@ public class TiffMetadataTests [Theory] [InlineData(Calliphora_BiColorUncompressed, 1)] [InlineData(GrayscaleUncompressed, 8)] + [InlineData(GrayscaleUncompressed16Bit, 16)] [InlineData(RgbUncompressed, 24)] public void Identify_DetectsCorrectBitPerPixel(string imagePath, int expectedBitsPerPixel) { diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 2de508b75c..c714b2f510 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -767,6 +767,7 @@ public static class TestImages public const string Calliphora_GrayscaleDeflate_Predictor = "Tiff/Calliphora_gray_deflate_predictor.tiff"; public const string Calliphora_GrayscaleLzw_Predictor = "Tiff/Calliphora_gray_lzw_predictor.tiff"; public const string Calliphora_GrayscaleDeflate = "Tiff/Calliphora_gray_deflate.tiff"; + public const string Calliphora_GrayscaleUncompressed16Bit = "Tiff/Calliphora_grayscale_uncompressed_16bit.tiff"; public const string Calliphora_RgbDeflate_Predictor = "Tiff/Calliphora_rgb_deflate_predictor.tiff"; public const string Calliphora_RgbJpeg = "Tiff/Calliphora_rgb_jpeg.tiff"; public const string Calliphora_PaletteUncompressed = "Tiff/Calliphora_palette_uncompressed.tiff"; @@ -798,6 +799,7 @@ public static class TestImages public const string GrayscaleDeflateMultistrip = "Tiff/grayscale_deflate_multistrip.tiff"; public const string GrayscaleUncompressed = "Tiff/grayscale_uncompressed.tiff"; + public const string GrayscaleUncompressed16Bit = "Tiff/grayscale_uncompressed_16bit.tiff"; public const string GrayscaleJpegCompressed = "Tiff/JpegCompressedGray.tiff"; public const string PaletteDeflateMultistrip = "Tiff/palette_grayscale_deflate_multistrip.tiff"; public const string PaletteUncompressed = "Tiff/palette_uncompressed.tiff"; diff --git a/tests/Images/Input/Tiff/Calliphora_grayscale_uncompressed_16bit.tiff b/tests/Images/Input/Tiff/Calliphora_grayscale_uncompressed_16bit.tiff new file mode 100644 index 0000000000..62d63a124b --- /dev/null +++ b/tests/Images/Input/Tiff/Calliphora_grayscale_uncompressed_16bit.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42077e6e0d0e7e32bdc0dadb837aad03fd4ae9ceff158bdf213ea9b76dbc36f1 +size 119601 diff --git a/tests/Images/Input/Tiff/grayscale_uncompressed_16bit.tiff b/tests/Images/Input/Tiff/grayscale_uncompressed_16bit.tiff new file mode 100644 index 0000000000..85391d9fe0 --- /dev/null +++ b/tests/Images/Input/Tiff/grayscale_uncompressed_16bit.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49de8d78dc22c4c7e62b0c02ae409550c0247c49ec4685162a0fe986d3280aa7 +size 131294 From a43ac0cf539a28ece855baf53afa892ab1293f8e Mon Sep 17 00:00:00 2001 From: Petar Tasev Date: Wed, 1 Feb 2023 22:18:01 -0800 Subject: [PATCH 37/37] Added compressed grayscale 16 bit decoder tests --- tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs | 5 ++++- tests/ImageSharp.Tests/TestImages.cs | 3 +++ tests/Images/Input/Tiff/Calliphora_gray_deflate_16bit.tiff | 3 +++ .../Input/Tiff/Calliphora_gray_deflate_predictor_16bit.tiff | 3 +++ .../Input/Tiff/Calliphora_gray_lzw_predictor_16bit.tiff | 3 +++ 5 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/Images/Input/Tiff/Calliphora_gray_deflate_16bit.tiff create mode 100644 tests/Images/Input/Tiff/Calliphora_gray_deflate_predictor_16bit.tiff create mode 100644 tests/Images/Input/Tiff/Calliphora_gray_lzw_predictor_16bit.tiff diff --git a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs index 31b9ffb318..05c1c5a138 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/TiffDecoderTests.cs @@ -35,7 +35,7 @@ public class TiffDecoderTests : TiffDecoderBaseTester using MemoryStream stream = new(testFile.Bytes, false); ImageInfo info = Image.Identify(stream); - Assert.Equal(expectedPixelSize, info.PixelType?.BitsPerPixel); + Assert.Equal(expectedPixelSize, info.PixelType.BitsPerPixel); Assert.Equal(expectedWidth, info.Width); Assert.Equal(expectedHeight, info.Height); Assert.NotNull(info.Metadata); @@ -601,6 +601,8 @@ public class TiffDecoderTests : TiffDecoderBaseTester [WithFile(RgbDeflateMultistrip, PixelTypes.Rgba32)] [WithFile(Calliphora_GrayscaleDeflate, PixelTypes.Rgba32)] [WithFile(Calliphora_GrayscaleDeflate_Predictor, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleDeflate16Bit, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleDeflate_Predictor16Bit, PixelTypes.Rgba32)] [WithFile(Calliphora_RgbDeflate_Predictor, PixelTypes.Rgba32)] [WithFile(RgbDeflate, PixelTypes.Rgba32)] [WithFile(RgbDeflatePredictor, PixelTypes.Rgba32)] @@ -617,6 +619,7 @@ public class TiffDecoderTests : TiffDecoderBaseTester [WithFile(Calliphora_RgbPaletteLzw_Predictor, PixelTypes.Rgba32)] [WithFile(Calliphora_RgbLzwPredictor, PixelTypes.Rgba32)] [WithFile(Calliphora_GrayscaleLzw_Predictor, PixelTypes.Rgba32)] + [WithFile(Calliphora_GrayscaleLzw_Predictor16Bit, PixelTypes.Rgba32)] [WithFile(SmallRgbLzw, PixelTypes.Rgba32)] public void TiffDecoder_CanDecode_LzwCompressed(TestImageProvider provider) where TPixel : unmanaged, IPixel => TestTiffDecoder(provider); diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index c714b2f510..c282d81665 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -768,6 +768,9 @@ public static class TestImages public const string Calliphora_GrayscaleLzw_Predictor = "Tiff/Calliphora_gray_lzw_predictor.tiff"; public const string Calliphora_GrayscaleDeflate = "Tiff/Calliphora_gray_deflate.tiff"; public const string Calliphora_GrayscaleUncompressed16Bit = "Tiff/Calliphora_grayscale_uncompressed_16bit.tiff"; + public const string Calliphora_GrayscaleDeflate_Predictor16Bit = "Tiff/Calliphora_gray_deflate_predictor_16bit.tiff"; + public const string Calliphora_GrayscaleLzw_Predictor16Bit = "Tiff/Calliphora_gray_lzw_predictor_16bit.tiff"; + public const string Calliphora_GrayscaleDeflate16Bit = "Tiff/Calliphora_gray_deflate_16bit.tiff"; public const string Calliphora_RgbDeflate_Predictor = "Tiff/Calliphora_rgb_deflate_predictor.tiff"; public const string Calliphora_RgbJpeg = "Tiff/Calliphora_rgb_jpeg.tiff"; public const string Calliphora_PaletteUncompressed = "Tiff/Calliphora_palette_uncompressed.tiff"; diff --git a/tests/Images/Input/Tiff/Calliphora_gray_deflate_16bit.tiff b/tests/Images/Input/Tiff/Calliphora_gray_deflate_16bit.tiff new file mode 100644 index 0000000000..3864a62444 --- /dev/null +++ b/tests/Images/Input/Tiff/Calliphora_gray_deflate_16bit.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fdf62eb43c0349cb8c6ad67e5389a0f307944d8a8e760667a7f78fcc48a9ffa +size 62698 diff --git a/tests/Images/Input/Tiff/Calliphora_gray_deflate_predictor_16bit.tiff b/tests/Images/Input/Tiff/Calliphora_gray_deflate_predictor_16bit.tiff new file mode 100644 index 0000000000..b25f2d29ea --- /dev/null +++ b/tests/Images/Input/Tiff/Calliphora_gray_deflate_predictor_16bit.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8040010e7f760d09dda49145050b07f32826037c11686d976b4b7949a0c40c18 +size 54086 diff --git a/tests/Images/Input/Tiff/Calliphora_gray_lzw_predictor_16bit.tiff b/tests/Images/Input/Tiff/Calliphora_gray_lzw_predictor_16bit.tiff new file mode 100644 index 0000000000..8f7e72441a --- /dev/null +++ b/tests/Images/Input/Tiff/Calliphora_gray_lzw_predictor_16bit.tiff @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67246d3bfc0c361fae21db04fa0251168c7e12abe3c3cc134cd1d685fb09876f +size 58392