diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index ae5069be1..a6f529ee3 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -1,10 +1,15 @@  - - An extension to ImageSharp that allows the drawing of images, paths, and text. + SixLabors.ImageSharp.Drawing + SixLabors and contributors + Six Labors + Copyright (c) Six Labors and contributors. + SixLabors.ImageSharp + An extension to ImageSharp that allows the drawing of images, paths, and text. + en + $(packageversion) 0.0.1 - SixLabors and contributors netstandard1.3;netstandard2.0 7.3 true @@ -17,15 +22,6 @@ http://www.apache.org/licenses/LICENSE-2.0 git https://github.com/SixLabors/ImageSharp - false - false - false - false - false - false - false - false - false full portable True diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 9e7624480..eb6991e6a 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -1,6 +1,9 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System.Numerics; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.ImageSharp.Processing.Processors.Quantization; @@ -15,6 +18,17 @@ namespace SixLabors.ImageSharp.Advanced /// public static class AotCompilerTools { + static AotCompilerTools() + { + System.Runtime.CompilerServices.Unsafe.SizeOf(); + System.Runtime.CompilerServices.Unsafe.SizeOf(); + System.Runtime.CompilerServices.Unsafe.SizeOf(); + System.Runtime.CompilerServices.Unsafe.SizeOf(); + System.Runtime.CompilerServices.Unsafe.SizeOf(); + System.Runtime.CompilerServices.Unsafe.SizeOf(); + System.Runtime.CompilerServices.Unsafe.SizeOf(); + } + /// /// Seeds the compiler using the given pixel format. /// @@ -27,6 +41,13 @@ namespace SixLabors.ImageSharp.Advanced AotCompileWuQuantizer(); AotCompileDithering(); + System.Runtime.CompilerServices.Unsafe.SizeOf(); + + AotCodec(new Formats.Png.PngDecoder(), new Formats.Png.PngEncoder()); + AotCodec(new Formats.Bmp.BmpDecoder(), new Formats.Bmp.BmpEncoder()); + AotCodec(new Formats.Gif.GifDecoder(), new Formats.Gif.GifEncoder()); + AotCodec(new Formats.Jpeg.JpegDecoder(), new Formats.Jpeg.JpegEncoder()); + // TODO: Do the discovery work to figure out what works and what doesn't. } @@ -99,5 +120,31 @@ namespace SixLabors.ImageSharp.Advanced TPixel pixel = default; test.Dither(new ImageFrame(Configuration.Default, 1, 1), pixel, pixel, 0, 0, 0, 0, 0, 0); } + + /// + /// This method pre-seeds the decoder and encoder for a given pixel format in the AoT compiler for iOS. + /// + /// The image decoder to seed. + /// The image encoder to seed. + /// The pixel format. + private static void AotCodec(IImageDecoder decoder, IImageEncoder encoder) + where TPixel : struct, IPixel + { + try + { + decoder.Decode(Configuration.Default, null); + } + catch + { + } + + try + { + encoder.Encode(null, null); + } + catch + { + } + } } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/CieLab.cs b/src/ImageSharp/ColorSpaces/CieLab.cs index ea6df86e2..146acf12e 100644 --- a/src/ImageSharp/ColorSpaces/CieLab.cs +++ b/src/ImageSharp/ColorSpaces/CieLab.cs @@ -118,13 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public static bool operator !=(CieLab left, CieLab right) => !left.Equals(right); /// - public override int GetHashCode() - { - int hash = this.L.GetHashCode(); - hash = HashHelpers.Combine(hash, this.A.GetHashCode()); - hash = HashHelpers.Combine(hash, this.B.GetHashCode()); - return HashHelpers.Combine(hash, this.WhitePoint.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.L, this.A, this.B, this.WhitePoint); /// public override string ToString() => FormattableString.Invariant($"CieLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs index f1a7425e9..074bc1516 100644 --- a/src/ImageSharp/ColorSpaces/CieLch.cs +++ b/src/ImageSharp/ColorSpaces/CieLch.cs @@ -122,10 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// public override int GetHashCode() { - int hash = this.L.GetHashCode(); - hash = HashHelpers.Combine(hash, this.C.GetHashCode()); - hash = HashHelpers.Combine(hash, this.H.GetHashCode()); - return HashHelpers.Combine(hash, this.WhitePoint.GetHashCode()); + return HashCode.Combine(this.L, this.C, this.H, this.WhitePoint); } /// diff --git a/src/ImageSharp/ColorSpaces/CieLchuv.cs b/src/ImageSharp/ColorSpaces/CieLchuv.cs index 256b5dc0f..ab6f639a2 100644 --- a/src/ImageSharp/ColorSpaces/CieLchuv.cs +++ b/src/ImageSharp/ColorSpaces/CieLchuv.cs @@ -119,13 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public static bool operator !=(CieLchuv left, CieLchuv right) => !left.Equals(right); /// - public override int GetHashCode() - { - int hash = this.L.GetHashCode(); - hash = HashHelpers.Combine(hash, this.C.GetHashCode()); - hash = HashHelpers.Combine(hash, this.H.GetHashCode()); - return HashHelpers.Combine(hash, this.WhitePoint.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.L, this.C, this.H, this.WhitePoint); /// public override string ToString() => FormattableString.Invariant($"CieLchuv({this.L:#0.##}, {this.C:#0.##}, {this.H:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/CieLuv.cs b/src/ImageSharp/ColorSpaces/CieLuv.cs index 8fe073d6b..d54d92b62 100644 --- a/src/ImageSharp/ColorSpaces/CieLuv.cs +++ b/src/ImageSharp/ColorSpaces/CieLuv.cs @@ -119,13 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public static bool operator !=(CieLuv left, CieLuv right) => !left.Equals(right); /// - public override int GetHashCode() - { - int hash = this.L.GetHashCode(); - hash = HashHelpers.Combine(hash, this.U.GetHashCode()); - hash = HashHelpers.Combine(hash, this.V.GetHashCode()); - return HashHelpers.Combine(hash, this.WhitePoint.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.L, this.U, this.V, this.WhitePoint); /// public override string ToString() => FormattableString.Invariant($"CieLuv({this.L:#0.##}, {this.U:#0.##}, {this.V:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs index f625bb761..49c1da9f1 100644 --- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs @@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() => HashHelpers.Combine(this.X.GetHashCode(), this.Y.GetHashCode()); + public override int GetHashCode() => HashCode.Combine(this.X, this.Y); /// public override string ToString() => FormattableString.Invariant($"CieXyChromaticityCoordinates({this.X:#0.##}, {this.Y:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/CieXyy.cs b/src/ImageSharp/ColorSpaces/CieXyy.cs index 7137360e9..fff296945 100644 --- a/src/ImageSharp/ColorSpaces/CieXyy.cs +++ b/src/ImageSharp/ColorSpaces/CieXyy.cs @@ -83,12 +83,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public static bool operator !=(CieXyy left, CieXyy right) => !left.Equals(right); /// - public override int GetHashCode() - { - int hash = this.X.GetHashCode(); - hash = HashHelpers.Combine(hash, this.Y.GetHashCode()); - return HashHelpers.Combine(hash, this.Yl.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.X, this.Y, this.Yl); /// public override string ToString() => FormattableString.Invariant($"CieXyy({this.X:#0.##}, {this.Y:#0.##}, {this.Yl:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs index c0ed35660..30521476e 100644 --- a/src/ImageSharp/ColorSpaces/CieXyz.cs +++ b/src/ImageSharp/ColorSpaces/CieXyz.cs @@ -86,12 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public Vector3 ToVector3() => new Vector3(this.X, this.Y, this.Z); /// - public override int GetHashCode() - { - int hash = this.X.GetHashCode(); - hash = HashHelpers.Combine(hash, this.Y.GetHashCode()); - return HashHelpers.Combine(hash, this.Z.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.X, this.Y, this.Z); /// public override string ToString() => FormattableString.Invariant($"CieXyz({this.X:#0.##}, {this.Y:#0.##}, {this.Z:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs index 634667c0c..04901126c 100644 --- a/src/ImageSharp/ColorSpaces/Cmyk.cs +++ b/src/ImageSharp/ColorSpaces/Cmyk.cs @@ -90,13 +90,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - int hash = this.C.GetHashCode(); - hash = HashHelpers.Combine(hash, this.M.GetHashCode()); - hash = HashHelpers.Combine(hash, this.Y.GetHashCode()); - return HashHelpers.Combine(hash, this.K.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.C, this.M, this.Y, this.K); /// public override string ToString() => FormattableString.Invariant($"Cmyk({this.C:#0.##}, {this.M:#0.##}, {this.Y:#0.##}, {this.K:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs index 68b4d95fc..4c69133e0 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs @@ -86,14 +86,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation } /// - public override int GetHashCode() - { - unchecked - { - int hashCode = this.R.GetHashCode(); - hashCode = (hashCode * 397) ^ this.G.GetHashCode(); - return (hashCode * 397) ^ this.B.GetHashCode(); - } - } + public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B); } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs index 73aa60b6c..639d0b293 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.ColorSpaces.Companding; @@ -57,10 +58,9 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation } /// - public override int GetHashCode() - { - int hash = base.GetHashCode(); - return HashHelpers.Combine(hash, this.Gamma.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine( + this.WhitePoint, + this.ChromaticityCoordinates, + this.Gamma); } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs index 5a89321c8..6051f5286 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; + namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation { /// @@ -76,8 +78,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation /// public override int GetHashCode() { - int hash = this.WhitePoint.GetHashCode(); - return HashHelpers.Combine(hash, this.ChromaticityCoordinates.GetHashCode()); + return HashCode.Combine(this.WhitePoint, this.ChromaticityCoordinates); } } } \ No newline at end of file diff --git a/src/ImageSharp/ColorSpaces/Hsl.cs b/src/ImageSharp/ColorSpaces/Hsl.cs index f6e531df3..04b3bea41 100644 --- a/src/ImageSharp/ColorSpaces/Hsl.cs +++ b/src/ImageSharp/ColorSpaces/Hsl.cs @@ -84,12 +84,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - int hash = this.H.GetHashCode(); - hash = HashHelpers.Combine(hash, this.S.GetHashCode()); - return HashHelpers.Combine(hash, this.L.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.H, this.S, this.L); /// public override string ToString() => FormattableString.Invariant($"Hsl({this.H:#0.##}, {this.S:#0.##}, {this.L:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/Hsv.cs b/src/ImageSharp/ColorSpaces/Hsv.cs index 631f03d09..8ccc74ae0 100644 --- a/src/ImageSharp/ColorSpaces/Hsv.cs +++ b/src/ImageSharp/ColorSpaces/Hsv.cs @@ -82,12 +82,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - int hash = this.H.GetHashCode(); - hash = HashHelpers.Combine(hash, this.S.GetHashCode()); - return HashHelpers.Combine(hash, this.V.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.H, this.S, this.V); /// public override string ToString() => FormattableString.Invariant($"Hsv({this.H:#0.##}, {this.S:#0.##}, {this.V:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs index f4fa29d31..dcae65e42 100644 --- a/src/ImageSharp/ColorSpaces/HunterLab.cs +++ b/src/ImageSharp/ColorSpaces/HunterLab.cs @@ -119,10 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces [MethodImpl(InliningOptions.ShortMethod)] public override int GetHashCode() { - int hash = this.L.GetHashCode(); - hash = HashHelpers.Combine(hash, this.A.GetHashCode()); - hash = HashHelpers.Combine(hash, this.B.GetHashCode()); - return HashHelpers.Combine(hash, this.WhitePoint.GetHashCode()); + return HashCode.Combine(this.L, this.A, this.B, this.WhitePoint); } /// diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs index ec6d18be2..46b227596 100644 --- a/src/ImageSharp/ColorSpaces/LinearRgb.cs +++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs @@ -126,12 +126,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - int hash = this.R.GetHashCode(); - hash = HashHelpers.Combine(hash, this.G.GetHashCode()); - return HashHelpers.Combine(hash, this.B.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B); /// public override string ToString() => FormattableString.Invariant($"LinearRgb({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/Lms.cs b/src/ImageSharp/ColorSpaces/Lms.cs index 0a8b7aa7b..0ee56abbc 100644 --- a/src/ImageSharp/ColorSpaces/Lms.cs +++ b/src/ImageSharp/ColorSpaces/Lms.cs @@ -87,12 +87,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public Vector3 ToVector3() => new Vector3(this.L, this.M, this.S); /// - public override int GetHashCode() - { - int hash = this.L.GetHashCode(); - hash = HashHelpers.Combine(hash, this.M.GetHashCode()); - return HashHelpers.Combine(hash, this.S.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.L, this.M, this.S); /// public override string ToString() => FormattableString.Invariant($"Lms({this.L:#0.##}, {this.M:#0.##}, {this.S:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs index 97fafbaf3..cdc9e90ad 100644 --- a/src/ImageSharp/ColorSpaces/Rgb.cs +++ b/src/ImageSharp/ColorSpaces/Rgb.cs @@ -147,12 +147,7 @@ namespace SixLabors.ImageSharp.ColorSpaces public Vector3 ToVector3() => new Vector3(this.R, this.G, this.B); /// - public override int GetHashCode() - { - int hash = this.R.GetHashCode(); - hash = HashHelpers.Combine(hash, this.G.GetHashCode()); - return HashHelpers.Combine(hash, this.B.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B); /// public override string ToString() => FormattableString.Invariant($"Rgb({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##})"); diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs index 6aa191c2d..b0563bb89 100644 --- a/src/ImageSharp/ColorSpaces/YCbCr.cs +++ b/src/ImageSharp/ColorSpaces/YCbCr.cs @@ -83,12 +83,7 @@ namespace SixLabors.ImageSharp.ColorSpaces /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - int hash = this.Y.GetHashCode(); - hash = HashHelpers.Combine(hash, this.Cb.GetHashCode()); - return HashHelpers.Combine(hash, this.Cr.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.Y, this.Cb, this.Cr); /// public override string ToString() => FormattableString.Invariant($"YCbCr({this.Y}, {this.Cb}, {this.Cr})"); diff --git a/src/ImageSharp/Common/Helpers/TolerantMath.cs b/src/ImageSharp/Common/Helpers/TolerantMath.cs index 5347efcc0..bef7eb161 100644 --- a/src/ImageSharp/Common/Helpers/TolerantMath.cs +++ b/src/ImageSharp/Common/Helpers/TolerantMath.cs @@ -16,6 +16,13 @@ namespace SixLabors.ImageSharp private readonly double negEpsilon; + /// + /// A read-only default instance for using 1e-8 as epsilon. + /// It is a field so it can be passed as an 'in' parameter. + /// Does not necessarily fit all use cases! + /// + public static readonly TolerantMath Default = new TolerantMath(1e-8); + public TolerantMath(double epsilon) { DebugGuard.MustBeGreaterThan(epsilon, 0, nameof(epsilon)); @@ -24,8 +31,6 @@ namespace SixLabors.ImageSharp this.negEpsilon = -epsilon; } - public static TolerantMath Default { get; } = new TolerantMath(1e-8); - /// /// == 0 /// diff --git a/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs b/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs index 1d1734a86..782333219 100644 --- a/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs +++ b/src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.ParallelUtils Rectangle rectangle, in ParallelExecutionSettings parallelSettings, Action> body) - where T : struct + where T : unmanaged { int maxSteps = DivideCeil(rectangle.Width * rectangle.Height, parallelSettings.MinimumPixelsProcessedPerTask); @@ -135,7 +135,7 @@ namespace SixLabors.ImageSharp.ParallelUtils Rectangle rectangle, Configuration configuration, Action> body) - where T : struct + where T : unmanaged { IterateRowsWithTempBuffer(rectangle, configuration.GetParallelSettings(), body); } diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index ef3ca24ee..68528edcd 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { try { - this.ReadImageHeaders(stream, out bool inverted, out byte[] palette); + int bytesPerColorMapEntry = this.ReadImageHeaders(stream, out bool inverted, out byte[] palette); var image = new Image(this.configuration, this.infoHeader.Width, this.infoHeader.Height, this.metaData); @@ -137,6 +137,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp this.infoHeader.Width, this.infoHeader.Height, this.infoHeader.BitsPerPixel, + bytesPerColorMapEntry, inverted); } @@ -329,18 +330,20 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// The containing the colors. /// The width of the bitmap. /// The height of the bitmap. - /// The number of bits per pixel. + /// The number of bits per pixel. + /// Usually 4 bytes, but in case of Windows 2.x bitmaps or OS/2 1.x bitmaps + /// the bytes per color palette entry's can be 3 bytes instead of 4. /// Whether the bitmap is inverted. - private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int width, int height, int bits, bool inverted) + private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int width, int height, int bitsPerPixel, int bytesPerColorMapEntry, bool inverted) where TPixel : struct, IPixel { // Pixels per byte (bits per pixel) - int ppb = 8 / bits; + int ppb = 8 / bitsPerPixel; int arrayWidth = (width + ppb - 1) / ppb; // Bit mask - int mask = 0xFF >> (8 - bits); + int mask = 0xFF >> (8 - bitsPerPixel); // Rows are aligned on 4 byte boundaries int padding = arrayWidth % 4; @@ -366,7 +369,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp int colOffset = x * ppb; for (int shift = 0, newX = colOffset; shift < ppb && newX < width; shift++, newX++) { - int colorIndex = ((rowSpan[offset] >> (8 - bits - (shift * bits))) & mask) * 4; + int colorIndex = ((rowSpan[offset] >> (8 - bitsPerPixel - (shift * bitsPerPixel))) & mask) * bytesPerColorMapEntry; color.FromBgr24(Unsafe.As(ref colors[colorIndex])); pixelRow[newX] = color; @@ -510,6 +513,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp // 12 bytes this.infoHeader = BmpInfoHeader.ParseCore(buffer); } + else if (headerSize == BmpInfoHeader.Os22ShortSize) + { + // 16 bytes + this.infoHeader = BmpInfoHeader.ParseOs22Short(buffer); + } else if (headerSize >= BmpInfoHeader.Size) { // >= 40 bytes @@ -571,7 +579,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Reads the and from the stream and sets the corresponding fields. /// - private void ReadImageHeaders(Stream stream, out bool inverted, out byte[] palette) + /// Bytes per color palette entry. Usually 4 bytes, but in case of Windows 2.x bitmaps or OS/2 1.x bitmaps + /// the bytes per color palette entry's can be 3 bytes instead of 4. + private int ReadImageHeaders(Stream stream, out bool inverted, out byte[] palette) { this.stream = stream; @@ -591,6 +601,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp } int colorMapSize = -1; + int bytesPerColorMapEntry = 4; if (this.infoHeader.ClrUsed == 0) { @@ -598,12 +609,15 @@ namespace SixLabors.ImageSharp.Formats.Bmp || this.infoHeader.BitsPerPixel == 4 || this.infoHeader.BitsPerPixel == 8) { - colorMapSize = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel) * 4; + int colorMapSizeBytes = this.fileHeader.Offset - BmpFileHeader.Size - this.infoHeader.HeaderSize; + int colorCountForBitDepth = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel); + bytesPerColorMapEntry = colorMapSizeBytes / colorCountForBitDepth; + colorMapSize = colorMapSizeBytes; } } else { - colorMapSize = this.infoHeader.ClrUsed * 4; + colorMapSize = this.infoHeader.ClrUsed * bytesPerColorMapEntry; } palette = null; @@ -622,6 +636,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp } this.infoHeader.VerifyDimensions(); + + return bytesPerColorMapEntry; } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs index 4dd63a962..5177bc325 100644 --- a/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs +++ b/src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs @@ -26,6 +26,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// public const int CoreSize = 12; + /// + /// Defines the size of the short variant of the OS22XBITMAPHEADER data structure in the bitmap file. + /// + public const int Os22ShortSize = 16; + /// /// Defines the size of the biggest supported header data structure in the bitmap file. /// @@ -143,7 +148,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp /// /// Parses the BITMAPCOREHEADER consisting of the headerSize, width, height, planes, and bitsPerPixel fields (12 bytes). /// - /// The data to parse, + /// The data to parse. /// Parsed header /// public static BmpInfoHeader ParseCore(ReadOnlySpan data) @@ -156,6 +161,23 @@ namespace SixLabors.ImageSharp.Formats.Bmp bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(10, 2))); } + /// + /// Parses a short variant of the OS22XBITMAPHEADER. It is identical to the BITMAPCOREHEADER, except that the width and height + /// are 4 bytes instead of 2. + /// + /// The data to parse. + /// Parsed header + /// + public static BmpInfoHeader ParseOs22Short(ReadOnlySpan data) + { + return new BmpInfoHeader( + headerSize: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(0, 4)), + width: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(4, 4)), + height: BinaryPrimitives.ReadInt32LittleEndian(data.Slice(8, 4)), + planes: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(12, 2)), + bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(14, 2))); + } + public unsafe void WriteTo(Span buffer) { ref BmpInfoHeader dest = ref Unsafe.As(ref MemoryMarshal.GetReference(buffer)); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs index af0938d30..43de39ac7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs @@ -100,13 +100,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// public override int GetHashCode() { - return HashHelpers.Combine( - this.DCTEncodeVersion.GetHashCode(), - HashHelpers.Combine( - this.APP14Flags0.GetHashCode(), - HashHelpers.Combine( - this.APP14Flags1.GetHashCode(), - this.ColorTransform.GetHashCode()))); + return HashCode.Combine( + this.DCTEncodeVersion, + this.APP14Flags0, + this.APP14Flags1, + this.ColorTransform); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs index 4bff49248..c51a2f4da 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs @@ -112,13 +112,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder /// public override int GetHashCode() { - return HashHelpers.Combine( - this.MajorVersion.GetHashCode(), - HashHelpers.Combine( - this.MinorVersion.GetHashCode(), - HashHelpers.Combine( - this.DensityUnits.GetHashCode(), - HashHelpers.Combine(this.XDensity, this.YDensity)))); + return HashCode.Combine( + this.MajorVersion, + this.MinorVersion, + this.DensityUnits, + this.XDensity, + this.YDensity); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index c52858d4c..af6dfd9ec 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -556,12 +556,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg if (this.exifData is null) { // The first 6 bytes (Exif00) will be skipped, because this is Jpeg specific - this.exifData = profile.Skip(Exif00).ToArray(); + this.exifData = profile.AsSpan(Exif00).ToArray(); } else { // If the EXIF information exceeds 64K, it will be split over multiple APP1 markers - this.ExtendProfile(ref this.exifData, profile.Skip(Exif00).ToArray()); + this.ExtendProfile(ref this.exifData, profile.AsSpan(Exif00).ToArray()); } } } diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 292de007c..216f3129f 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -237,7 +237,7 @@ namespace SixLabors.ImageSharp.Formats.Png } // Use the metadata to determine what quantization depth to use if no quantizer has been set. - if (this.quantizer == null) + if (this.quantizer is null) { this.quantizer = new WuQuantizer(ImageMaths.GetColorCountForBitDepth(bits)); } diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index c19c92426..1cdee81a2 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -1,10 +1,15 @@  - A cross-platform library for the processing of image files; written in C# SixLabors.ImageSharp + Six Labors and contributors + Six Labors + Copyright (c) Six Labors and contributors. + SixLabors.ImageSharp + A cross-platform library for the processing of image files; written in C# + en + $(packageversion) 0.0.1 - Six Labors and contributors netstandard1.3;netstandard2.0;netcoreapp2.1;net472 true true @@ -16,20 +21,11 @@ http://www.apache.org/licenses/LICENSE-2.0 git https://github.com/SixLabors/ImageSharp - false - false - false - false - false - false - false - false - false full portable True IOperation - Latest + 7.3 @@ -42,7 +38,7 @@ - + All diff --git a/src/ImageSharp/MetaData/ImageProperty.cs b/src/ImageSharp/MetaData/ImageProperty.cs index a08a95fed..24a3686de 100644 --- a/src/ImageSharp/MetaData/ImageProperty.cs +++ b/src/ImageSharp/MetaData/ImageProperty.cs @@ -99,19 +99,7 @@ namespace SixLabors.ImageSharp.MetaData /// /// A 32-bit signed integer that is the hash code for this instance. /// - public override int GetHashCode() - { - unchecked - { - int hashCode = this.Name.GetHashCode(); - if (this.Value != null) - { - hashCode = (hashCode * 397) ^ this.Value.GetHashCode(); - } - - return hashCode; - } - } + public override int GetHashCode() => HashCode.Combine(this.Name, this.Value); /// /// Returns the fully qualified type name of this instance. diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs index 100649c0f..8ec9eea27 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs @@ -27,9 +27,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif public ExifReader(byte[] exifData) { - DebugGuard.NotNull(exifData, nameof(exifData)); - - this.exifData = exifData; + this.exifData = exifData ?? throw new ArgumentNullException(nameof(exifData)); } private delegate TDataType ConverterMethod(ReadOnlySpan data); @@ -374,7 +372,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif private void AddInvalidTag(ExifTag tag) { - if (this.invalidTags == null) + if (this.invalidTags is null) { this.invalidTags = new List(); } diff --git a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs index ccacfd0bf..409c55253 100644 --- a/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs +++ b/src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs @@ -198,7 +198,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif } /// - public override int GetHashCode() => this.GetHashCode(this); + public override int GetHashCode() + { + return HashCode.Combine(this.Tag, this.DataType, this.Value); + } /// public override string ToString() @@ -714,20 +717,5 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif throw new NotSupportedException(); } } - - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private int GetHashCode(ExifValue exif) - { - int hashCode = exif.Tag.GetHashCode() ^ exif.DataType.GetHashCode(); - return hashCode ^ exif.Value?.GetHashCode() ?? hashCode; - } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs index a241acd21..efc2ca537 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs @@ -154,18 +154,15 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = (int)this.Type; - hashCode = (hashCode * 397) ^ this.G.GetHashCode(); - hashCode = (hashCode * 397) ^ this.A.GetHashCode(); - hashCode = (hashCode * 397) ^ this.B.GetHashCode(); - hashCode = (hashCode * 397) ^ this.C.GetHashCode(); - hashCode = (hashCode * 397) ^ this.D.GetHashCode(); - hashCode = (hashCode * 397) ^ this.E.GetHashCode(); - hashCode = (hashCode * 397) ^ this.F.GetHashCode(); - return hashCode; - } + return HashCode.Combine( + this.Type, + this.G.GetHashCode(), + this.A.GetHashCode(), + this.B.GetHashCode(), + this.C.GetHashCode(), + this.D.GetHashCode(), + this.E.GetHashCode(), + this.F.GetHashCode()); } } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs index 02ab301bd..de08485ac 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs @@ -73,13 +73,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = (int)this.CurveType; - hashCode = (hashCode * 397) ^ (this.XyzValues?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.ResponseArrays?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.CurveType, + this.XyzValues, + this.ResponseArrays); } private bool EqualsResponseArray(IccResponseCurve other) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs index 2687e10b6..4c6bb0785 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs @@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (int)this.Signature * 397; - } - } + public override int GetHashCode() => this.Signature.GetHashCode(); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs index a87dae8c5..e9a812d8c 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs @@ -110,13 +110,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.ColorantType; - hashCode = (hashCode * 397) ^ (this.ChannelValues?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.ColorantType, + this.ChannelValues); } private static double[][] GetColorantArray(IccColorantEncoding colorantType) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs index 54c205615..b5f8fd5c4 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs @@ -70,10 +70,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.ColorantNumber?.GetHashCode() ?? 0); - } + return HashCode.Combine(this.Signature, this.ColorantNumber); } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs index dd99a2f9f..9f2b4c90a 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs @@ -72,10 +72,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.ColorantData?.GetHashCode() ?? 0); - } + return HashCode.Combine(this.Signature, this.ColorantData); } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs index cc1aea319..4d393dfb3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs @@ -121,16 +121,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.PostScriptProductName?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.RenderingIntent0Crd?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.RenderingIntent1Crd?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.RenderingIntent2Crd?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.RenderingIntent3Crd?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.PostScriptProductName, + this.RenderingIntent0Crd, + this.RenderingIntent1Crd, + this.RenderingIntent2Crd, + this.RenderingIntent3Crd); } } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs index 77a913b14..0d34d3ceb 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs @@ -116,12 +116,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.CurveData?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.CurveData); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs index 451088290..0b8367303 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs @@ -91,13 +91,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.Data?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ this.IsAscii.GetHashCode(); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.Data, + this.IsAscii); } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs index 792c653f6..104d24309 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs @@ -66,10 +66,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - return (base.GetHashCode() * 397) ^ this.Value.GetHashCode(); - } + return HashCode.Combine(this.Signature, this.Value); } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs index a76310927..0a114ea1f 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs @@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs index 9a7f2123e..dd180b299 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs @@ -62,17 +62,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc : base(IccTypeSignature.Lut16, tagSignature) { Guard.NotNull(matrix, nameof(matrix)); - Guard.NotNull(inputValues, nameof(inputValues)); - Guard.NotNull(clutValues, nameof(clutValues)); - Guard.NotNull(outputValues, nameof(outputValues)); bool is3By3 = matrix.GetLength(0) == 3 && matrix.GetLength(1) == 3; Guard.IsTrue(is3By3, nameof(matrix), "Matrix must have a size of three by three"); this.Matrix = this.CreateMatrix(matrix); - this.InputValues = inputValues; - this.ClutValues = clutValues; - this.OutputValues = outputValues; + this.InputValues = inputValues ?? throw new ArgumentNullException(nameof(inputValues)); + this.ClutValues = clutValues ?? throw new ArgumentNullException(nameof(clutValues)); + this.OutputValues = outputValues ?? throw new ArgumentNullException(nameof(outputValues)); Guard.IsTrue(this.InputChannelCount == clutValues.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); Guard.IsTrue(this.OutputChannelCount == clutValues.OutputChannelCount, nameof(clutValues), "Output channel count does not match the CLUT size"); @@ -143,15 +140,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Matrix.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.InputValues?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.ClutValues?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.OutputValues?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.Matrix, + this.InputValues, + this.ClutValues, + this.OutputValues); } private Matrix4x4 CreateMatrix(float[,] matrix) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs index bc0335cd8..b345d14a5 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs @@ -62,17 +62,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc : base(IccTypeSignature.Lut8, tagSignature) { Guard.NotNull(matrix, nameof(matrix)); - Guard.NotNull(inputValues, nameof(inputValues)); - Guard.NotNull(clutValues, nameof(clutValues)); - Guard.NotNull(outputValues, nameof(outputValues)); bool is3By3 = matrix.GetLength(0) == 3 && matrix.GetLength(1) == 3; Guard.IsTrue(is3By3, nameof(matrix), "Matrix must have a size of three by three"); this.Matrix = this.CreateMatrix(matrix); - this.InputValues = inputValues; - this.ClutValues = clutValues; - this.OutputValues = outputValues; + this.InputValues = inputValues ?? throw new ArgumentNullException(nameof(inputValues)); + this.ClutValues = clutValues ?? throw new ArgumentNullException(nameof(clutValues)); + this.OutputValues = outputValues ?? throw new ArgumentNullException(nameof(outputValues)); Guard.IsTrue(this.InputChannelCount == clutValues.InputChannelCount, nameof(clutValues), "Input channel count does not match the CLUT size"); Guard.IsTrue(this.OutputChannelCount == clutValues.OutputChannelCount, nameof(clutValues), "Output channel count does not match the CLUT size"); @@ -146,15 +143,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Matrix.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.InputValues?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.ClutValues?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.OutputValues?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.Matrix, + this.InputValues, + this.ClutValues, + this.OutputValues); } private Matrix4x4 CreateMatrix(float[,] matrix) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs index 22d5f7b2f..f7c094632 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs @@ -183,19 +183,21 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ this.InputChannelCount; - hashCode = (hashCode * 397) ^ this.OutputChannelCount; - hashCode = (hashCode * 397) ^ this.Matrix3x3.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Matrix3x1.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.ClutValues?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.CurveB?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.CurveM?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.CurveA?.GetHashCode() ?? 0); - return hashCode; - } +#pragma warning disable SA1129 // Do not use default value type constructor + var hashCode = new HashCode(); +#pragma warning restore SA1129 // Do not use default value type constructor + + hashCode.Add(this.Signature); + hashCode.Add(this.InputChannelCount); + hashCode.Add(this.OutputChannelCount); + hashCode.Add(this.Matrix3x3); + hashCode.Add(this.Matrix3x1); + hashCode.Add(this.ClutValues); + hashCode.Add(this.CurveB); + hashCode.Add(this.CurveM); + hashCode.Add(this.CurveA); + + return hashCode.ToHashCode(); } private bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] entryCurves) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs index a739358b5..27572acd0 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs @@ -183,19 +183,21 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ this.InputChannelCount; - hashCode = (hashCode * 397) ^ this.OutputChannelCount; - hashCode = (hashCode * 397) ^ this.Matrix3x3.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Matrix3x1.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.ClutValues?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.CurveB?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.CurveM?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.CurveA?.GetHashCode() ?? 0); - return hashCode; - } +#pragma warning disable SA1129 // Do not use default value type constructor + var hashCode = new HashCode(); +#pragma warning restore SA1129 // Do not use default value type constructor + + hashCode.Add(this.Signature); + hashCode.Add(this.InputChannelCount); + hashCode.Add(this.OutputChannelCount); + hashCode.Add(this.Matrix3x3); + hashCode.Add(this.Matrix3x1); + hashCode.Add(this.ClutValues); + hashCode.Add(this.CurveB); + hashCode.Add(this.CurveM); + hashCode.Add(this.CurveA); + + return hashCode.ToHashCode(); } private bool EqualsCurve(IccTagDataEntry[] thisCurves, IccTagDataEntry[] entryCurves) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs index 262129a38..9247ca593 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs @@ -106,16 +106,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.Observer; - hashCode = (hashCode * 397) ^ this.XyzBacking.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.Geometry; - hashCode = (hashCode * 397) ^ this.Flare.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.Illuminant; - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.Observer, + this.XyzBacking, + this.Geometry, + this.Flare, + this.Illuminant); } } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs index 48ed048bf..1a06eb588 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs @@ -66,12 +66,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Texts?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Texts); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs index 1429a0a87..f13fdb17f 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs @@ -90,14 +90,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ this.InputChannelCount; - hashCode = (hashCode * 397) ^ this.OutputChannelCount; - hashCode = (hashCode * 397) ^ (this.Data?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.InputChannelCount, + this.OutputChannelCount, + this.Data); } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs index c32a45182..957b8d5c3 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs @@ -83,6 +83,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc if (colors.Length > 0) { coordinateCount = colors[0].DeviceCoordinates?.Length ?? 0; + Guard.IsFalse(colors.Any(t => (t.DeviceCoordinates?.Length ?? 0) != coordinateCount), nameof(colors), "Device coordinate count must be the same for all colors"); } @@ -154,16 +155,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ this.CoordinateCount; - hashCode = (hashCode * 397) ^ (this.Prefix?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.Suffix?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ this.VendorFlags; - hashCode = (hashCode * 397) ^ (this.Colors?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.CoordinateCount, + this.Prefix, + this.Suffix, + this.VendorFlags, + this.Colors); } } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs index 46719b80f..9ec497d3b 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc public IccParametricCurveTagDataEntry(IccParametricCurve curve, IccProfileTag tagSignature) : base(IccTypeSignature.ParametricCurve, tagSignature) { - this.Curve = curve; + this.Curve = curve ?? throw new ArgumentNullException(nameof(curve)); } /// @@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Curve?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Curve); } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs index da6fcd7a2..ff6911526 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs @@ -67,12 +67,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Descriptions?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Descriptions); } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs index 51528a073..c6cc0903c 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs @@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs index e2cd5860b..494aa2888 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs @@ -83,13 +83,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ this.ChannelCount.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.Curves?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.ChannelCount, + this.Curves); } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs index 0bf8abfca..a073291ad 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs @@ -77,13 +77,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.Flags; - hashCode = (hashCode * 397) ^ (this.Channels?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine(this.Signature, this.Flags, this.Channels); } } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs index da557e644..287f0efb0 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs @@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.SignatureData?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.SignatureData); } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs index ca1e4c491..8e6f4bc19 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs @@ -166,16 +166,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.Ascii?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.Unicode?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.ScriptCode?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (int)this.UnicodeLanguageCode; - hashCode = (hashCode * 397) ^ this.ScriptCodeCode.GetHashCode(); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.Ascii, + this.Unicode, + this.ScriptCode, + this.UnicodeLanguageCode, + this.ScriptCodeCode); } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs index f10712d96..ab3b3fb6f 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs @@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Text?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Text); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs index 19430dc7b..464cbb9e7 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs @@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs index d9c093bda..1e7a7f8a9 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs @@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs index 803191929..affdc8720 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs @@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs index 2973b9ae6..36d48d613 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs @@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs index 2391ce96a..b2f267757 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs @@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs index eed4f97d4..510930e39 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs @@ -86,14 +86,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ (this.UcrCurve?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.BgCurve?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.Description?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.UcrCurve, + this.BgCurve, + this.Description); } } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs index da206a968..a0089e735 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs @@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data); } } \ No newline at end of file diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs index 6be21dcc9..bd636d4f2 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs @@ -86,14 +86,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = base.GetHashCode(); - hashCode = (hashCode * 397) ^ this.IlluminantXyz.GetHashCode(); - hashCode = (hashCode * 397) ^ this.SurroundXyz.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.Illuminant; - return hashCode; - } + return HashCode.Combine( + this.Signature, + this.IlluminantXyz, + this.SurroundXyz, + this.Illuminant); } } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs index 4878d96e4..3f7cad3af 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs @@ -142,15 +142,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = this.Values?.GetHashCode() ?? 0; - hashCode = (hashCode * 397) ^ (int)this.DataType; - hashCode = (hashCode * 397) ^ this.InputChannelCount; - hashCode = (hashCode * 397) ^ this.OutputChannelCount; - hashCode = (hashCode * 397) ^ (this.GridPointCount?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.Values, + this.DataType, + this.InputChannelCount, + this.OutputChannelCount, + this.GridPointCount); } private bool EqualsValuesArray(IccClut other) diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs index 56aa8b335..8f273dd60 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs @@ -102,14 +102,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = this.Name.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Pcs1.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Pcs2.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Pcs3.GetHashCode(); - return hashCode; - } + return HashCode.Combine( + this.Name, + this.Pcs1, + this.Pcs2, + this.Pcs3); } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs index 5b013fc2c..b7cb5bc49 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs @@ -80,27 +80,23 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public bool Equals(IccNamedColor other) => - this.Name == other.Name && - this.PcsCoordinates.SequenceEqual(other.PcsCoordinates) && - this.DeviceCoordinates.SequenceEqual(other.DeviceCoordinates); + public bool Equals(IccNamedColor other) + { + return this.Name.Equals(other.Name) + && this.PcsCoordinates.SequenceEqual(other.PcsCoordinates) + && this.DeviceCoordinates.SequenceEqual(other.DeviceCoordinates); + } /// public override int GetHashCode() { - unchecked - { - int hashCode = this.Name.GetHashCode(); - hashCode = (hashCode * 397) ^ this.PcsCoordinates.GetHashCode(); - hashCode = (hashCode * 397) ^ this.DeviceCoordinates.GetHashCode(); - return hashCode; - } + return HashCode.Combine( + this.Name, + this.PcsCoordinates, + this.DeviceCoordinates); } /// - public override string ToString() - { - return this.Name; - } + public override string ToString() => this.Name; } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs index aad130b0d..745312f56 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs @@ -73,15 +73,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc this.Size == other.Size; /// - public override int GetHashCode() - { - return unchecked((int)(this.Offset ^ this.Size)); - } + public override int GetHashCode() => unchecked((int)(this.Offset ^ this.Size)); /// - public override string ToString() - { - return $"{this.Offset}; {this.Size}"; - } + public override string ToString() => $"{this.Offset}; {this.Size}"; } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs index 9db4bb9c4..7e7c527ea 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs @@ -28,15 +28,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc IccLocalizedString[] deviceManufacturerInfo, IccLocalizedString[] deviceModelInfo) { - Guard.NotNull(deviceManufacturerInfo, nameof(deviceManufacturerInfo)); - Guard.NotNull(deviceModelInfo, nameof(deviceModelInfo)); - this.DeviceManufacturer = deviceManufacturer; this.DeviceModel = deviceModel; this.DeviceAttributes = deviceAttributes; this.TechnologyInformation = technologyInformation; - this.DeviceManufacturerInfo = deviceManufacturerInfo; - this.DeviceModelInfo = deviceModelInfo; + this.DeviceManufacturerInfo = deviceManufacturerInfo ?? throw new ArgumentNullException(nameof(deviceManufacturerInfo)); + this.DeviceModelInfo = deviceModelInfo ?? throw new ArgumentNullException(nameof(deviceModelInfo)); } /// @@ -87,16 +84,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = (int)this.DeviceManufacturer; - hashCode = (hashCode * 397) ^ (int)this.DeviceModel; - hashCode = (hashCode * 397) ^ this.DeviceAttributes.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.TechnologyInformation; - hashCode = (hashCode * 397) ^ (this.DeviceManufacturerInfo?.GetHashCode() ?? 0); - hashCode = (hashCode * 397) ^ (this.DeviceModelInfo?.GetHashCode() ?? 0); - return hashCode; - } + return HashCode.Combine( + this.DeviceManufacturer, + this.DeviceModel, + this.DeviceAttributes, + this.TechnologyInformation, + this.DeviceManufacturerInfo, + this.DeviceModelInfo); } } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs index 138999710..f64d5409a 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs @@ -101,14 +101,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = this.Part1.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Part2.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Part3.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Part4.GetHashCode(); - return hashCode; - } + return HashCode.Combine( + this.Part1, + this.Part2, + this.Part3, + this.Part4); } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs index d5362ad70..ae451c5db 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs @@ -18,10 +18,8 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// Description of the profile public IccProfileSequenceIdentifier(IccProfileId id, IccLocalizedString[] description) { - Guard.NotNull(description, nameof(description)); - this.Id = id; - this.Description = description; + this.Description = description ?? throw new ArgumentNullException(nameof(description)); } /// @@ -46,12 +44,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc } /// - public override int GetHashCode() - { - unchecked - { - return (this.Id.GetHashCode() * 397) ^ (this.Description?.GetHashCode() ?? 0); - } - } + public override int GetHashCode() => HashCode.Combine(this.Id, this.Description); } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs index d1da2366e..8cae86992 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs @@ -73,20 +73,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc this.MeasurementValue == other.MeasurementValue; /// - public override int GetHashCode() - { - unchecked - { - int hashCode = this.DeviceCode.GetHashCode(); - hashCode = (hashCode * 397) ^ this.MeasurementValue.GetHashCode(); - return hashCode; - } - } + public override int GetHashCode() => HashCode.Combine(this.DeviceCode, this.MeasurementValue); /// - public override string ToString() - { - return $"Code: {this.DeviceCode}; Value: {this.MeasurementValue}"; - } + public override string ToString() => $"Code: {this.DeviceCode}; Value: {this.MeasurementValue}"; } } diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs index 1c4ac8465..e8885a66b 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs @@ -85,13 +85,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public override int GetHashCode() { - unchecked - { - int hashCode = this.Frequency.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Angle.GetHashCode(); - hashCode = (hashCode * 397) ^ (int)this.SpotShape; - return hashCode; - } + return HashCode.Combine(this.Frequency, this.Angle, this.SpotShape); } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs index 04357dcf6..d93e068c5 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs @@ -76,20 +76,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc /// public bool Equals(IccTagTableEntry other) => - this.Signature == other.Signature && - this.Offset == other.Offset && - this.DataSize == other.DataSize; + this.Signature.Equals(other.Signature) && + this.Offset.Equals(other.Offset) && + this.DataSize.Equals(other.DataSize); /// public override int GetHashCode() { - unchecked - { - int hashCode = this.Signature.GetHashCode(); - hashCode = (hashCode * 397) ^ this.Offset.GetHashCode(); - hashCode = (hashCode * 397) ^ this.DataSize.GetHashCode(); - return hashCode; - } + return HashCode.Combine(this.Signature, this.Offset, this.DataSize); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs index 9207f046c..96ff7da6f 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -189,10 +190,6 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode()); - return HashHelpers.Combine(hash, this.B.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.R, this.B, this.G); } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs index 293fe0acb..86565731d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -200,11 +201,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode()); - return HashHelpers.Combine(hash, this.B.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.R, this.B, this.G); /// public override string ToString() => $"Rgb24({this.R}, {this.G}, {this.B})"; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs index 81497e5f1..eda116a46 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs @@ -189,11 +189,6 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public override int GetHashCode() - { - return HashHelpers.Combine( - this.R.GetHashCode(), - HashHelpers.Combine(this.G.GetHashCode(), this.B.GetHashCode())); - } + public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B); } } \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs index ff4c69d70..d65a5ade7 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs @@ -197,11 +197,6 @@ namespace SixLabors.ImageSharp.PixelFormats } /// - public override int GetHashCode() - { - int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode()); - hash = HashHelpers.Combine(hash, this.B.GetHashCode()); - return HashHelpers.Combine(hash, this.A.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.R, this.G, this.B, this.A); } } \ No newline at end of file diff --git a/src/ImageSharp/Primitives/DenseMatrix{T}.cs b/src/ImageSharp/Primitives/DenseMatrix{T}.cs index 7cfa98ec1..170292e29 100644 --- a/src/ImageSharp/Primitives/DenseMatrix{T}.cs +++ b/src/ImageSharp/Primitives/DenseMatrix{T}.cs @@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.Primitives /// The at the specified position. public ref T this[int row, int column] { - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] get { this.CheckCoordinates(row, column); @@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.Primitives /// /// The representation on the source data. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public static implicit operator DenseMatrix(T[,] data) => new DenseMatrix(data); /// @@ -135,9 +135,9 @@ namespace SixLabors.ImageSharp.Primitives /// /// The representation on the source data. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] #pragma warning disable SA1008 // Opening parenthesis should be spaced correctly - public static implicit operator T[,] (DenseMatrix data) + public static implicit operator T[,] (in DenseMatrix data) #pragma warning restore SA1008 // Opening parenthesis should be spaced correctly { var result = new T[data.Rows, data.Columns]; @@ -154,17 +154,38 @@ namespace SixLabors.ImageSharp.Primitives return result; } + /// + /// Transposes the rows and columns of the dense matrix. + /// + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public DenseMatrix Transpose() + { + var result = new DenseMatrix(this.Rows, this.Columns); + + for (int y = 0; y < this.Rows; y++) + { + for (int x = 0; x < this.Columns; x++) + { + ref T value = ref result[x, y]; + value = this[y, x]; + } + } + + return result; + } + /// /// Fills the matrix with the given value /// /// The value to fill each item with - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public void Fill(T value) => this.Span.Fill(value); /// /// Clears the matrix setting each value to the default value for the element type /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] public void Clear() => this.Span.Clear(); /// diff --git a/src/ImageSharp/Primitives/ValueSize.cs b/src/ImageSharp/Primitives/ValueSize.cs index 8af9ba2e4..e5e086540 100644 --- a/src/ImageSharp/Primitives/ValueSize.cs +++ b/src/ImageSharp/Primitives/ValueSize.cs @@ -133,9 +133,6 @@ namespace SixLabors.ImageSharp.Primitives } /// - public override int GetHashCode() - { - return HashHelpers.Combine(this.Value.GetHashCode(), this.Type.GetHashCode()); - } + public override int GetHashCode() => HashCode.Combine(this.Value, this.Type); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs index 38dc638b9..644d6c9e1 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs @@ -29,8 +29,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { this.Radius = radius; this.kernelSize = (radius * 2) + 1; - this.KernelX = this.CreateBoxKernel(true); - this.KernelY = this.CreateBoxKernel(false); + this.KernelX = this.CreateBoxKernel(); + this.KernelY = this.KernelX.Transpose(); } /// @@ -49,24 +49,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public DenseMatrix KernelY { get; } /// - protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); - } + protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) => new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); /// /// Create a 1 dimensional Box kernel. /// - /// Whether to calculate a horizontal kernel. /// The - private DenseMatrix CreateBoxKernel(bool horizontal) + private DenseMatrix CreateBoxKernel() { int size = this.kernelSize; - DenseMatrix kernel = horizontal - ? new DenseMatrix(size, 1) - : new DenseMatrix(1, size); + var kernel = new DenseMatrix(size, 1); - kernel.Fill(1.0F / size); + kernel.Fill(1F / size); return kernel; } diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs index 3045b9993..b3bc15d39 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs @@ -4,7 +4,6 @@ using System; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Primitives; -using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Convolution @@ -26,11 +25,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// The 'sigma' value representing the weight of the blur. public GaussianBlurProcessor(float sigma = 3F) + : this(sigma, (int)MathF.Ceiling(sigma * 3)) { - this.kernelSize = ((int)Math.Ceiling(sigma) * 2) + 1; - this.Sigma = sigma; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); + // Kernel radius is calculated using the minimum viable value. + // http://chemaguerra.com/gaussian-filter-radius/ } /// @@ -40,11 +38,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// The 'radius' value representing the size of the area to sample. /// public GaussianBlurProcessor(int radius) + : this(radius / 3F, radius) { - this.kernelSize = (radius * 2) + 1; - this.Sigma = radius; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); } /// @@ -61,8 +56,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { this.kernelSize = (radius * 2) + 1; this.Sigma = sigma; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); + this.KernelX = this.CreateGaussianKernel(); + this.KernelY = this.KernelX.Transpose(); } /// @@ -82,22 +77,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); - } + => new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); /// /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function /// - /// Whether to calculate a horizontal kernel. /// The - private DenseMatrix CreateGaussianKernel(bool horizontal) + private DenseMatrix CreateGaussianKernel() { int size = this.kernelSize; float weight = this.Sigma; - DenseMatrix kernel = horizontal - ? new DenseMatrix(size, 1) - : new DenseMatrix(1, size); + var kernel = new DenseMatrix(size, 1); float sum = 0F; float midpoint = (size - 1) / 2F; @@ -107,30 +97,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution float x = i - midpoint; float gx = ImageMaths.Gaussian(x, weight); sum += gx; - if (horizontal) - { - kernel[0, i] = gx; - } - else - { - kernel[i, 0] = gx; - } + kernel[0, i] = gx; } // Normalize kernel so that the sum of all weights equals 1 - if (horizontal) - { - for (int i = 0; i < size; i++) - { - kernel[0, i] = kernel[0, i] / sum; - } - } - else + for (int i = 0; i < size; i++) { - for (int i = 0; i < size; i++) - { - kernel[i, 0] = kernel[i, 0] / sum; - } + kernel[0, i] /= sum; } return kernel; diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs index 18963c73c..786bf7757 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs @@ -27,11 +27,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// The 'sigma' value representing the weight of the sharpening. /// public GaussianSharpenProcessor(float sigma = 3F) + : this(sigma, (int)MathF.Ceiling(sigma * 3)) { - this.kernelSize = ((int)Math.Ceiling(sigma) * 2) + 1; - this.Sigma = sigma; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); + // Kernel radius is calculated using the minimum viable value. + // http://chemaguerra.com/gaussian-filter-radius/ } /// @@ -41,11 +40,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// The 'radius' value representing the size of the area to sample. /// public GaussianSharpenProcessor(int radius) + : this(radius / 3F, radius) { - this.kernelSize = (radius * 2) + 1; - this.Sigma = radius; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); } /// @@ -62,8 +58,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { this.kernelSize = (radius * 2) + 1; this.Sigma = sigma; - this.KernelX = this.CreateGaussianKernel(true); - this.KernelY = this.CreateGaussianKernel(false); + this.KernelX = this.CreateGaussianKernel(); + this.KernelY = this.KernelX.Transpose(); } /// @@ -83,91 +79,49 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration) - { - new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); - } + => new Convolution2PassProcessor(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration); /// /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function /// - /// Whether to calculate a horizontal kernel. /// The - private DenseMatrix CreateGaussianKernel(bool horizontal) + private DenseMatrix CreateGaussianKernel() { int size = this.kernelSize; float weight = this.Sigma; - DenseMatrix kernel = horizontal - ? new DenseMatrix(size, 1) - : new DenseMatrix(1, size); + var kernel = new DenseMatrix(size, 1); float sum = 0; - float midpoint = (size - 1) / 2f; + float midpoint = (size - 1) / 2F; for (int i = 0; i < size; i++) { float x = i - midpoint; float gx = ImageMaths.Gaussian(x, weight); sum += gx; - if (horizontal) - { - kernel[0, i] = gx; - } - else - { - kernel[i, 0] = gx; - } + kernel[0, i] = gx; } // Invert the kernel for sharpening. int midpointRounded = (int)midpoint; - - if (horizontal) + for (int i = 0; i < size; i++) { - for (int i = 0; i < size; i++) + if (i == midpointRounded) { - if (i == midpointRounded) - { - // Calculate central value - kernel[0, i] = (2F * sum) - kernel[0, i]; - } - else - { - // invert value - kernel[0, i] = -kernel[0, i]; - } + // Calculate central value + kernel[0, i] = (2F * sum) - kernel[0, i]; } - } - else - { - for (int i = 0; i < size; i++) + else { - if (i == midpointRounded) - { - // Calculate central value - kernel[i, 0] = (2 * sum) - kernel[i, 0]; - } - else - { - // invert value - kernel[i, 0] = -kernel[i, 0]; - } + // invert value + kernel[0, i] = -kernel[0, i]; } } // Normalize kernel so that the sum of all weights equals 1 - if (horizontal) - { - for (int i = 0; i < size; i++) - { - kernel[0, i] /= sum; - } - } - else + for (int i = 0; i < size; i++) { - for (int i = 0; i < size; i++) - { - kernel[i, 0] /= sum; - } + kernel[0, i] /= sum; } return kernel; diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs index f01865ec0..43f6c8a45 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs @@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering base.BeforeFrameApply(source, sourceRectangle, configuration); // Lazy init paletteVector: - if (this.paletteVector == null) + if (this.paletteVector is null) { this.paletteVector = new Vector4[this.Palette.Length]; PixelOperations.Instance.ToScaledVector4(configuration, this.Palette, this.paletteVector); diff --git a/src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs b/src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs index b7bea2c74..13660d30a 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs @@ -43,7 +43,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering => obj is PixelPair other && this.First.Equals(other.First) && this.Second.Equals(other.Second); /// - public override int GetHashCode() - => HashHelpers.Combine(this.First.GetHashCode(), this.Second.GetHashCode()); + public override int GetHashCode() => HashCode.Combine(this.First, this.Second); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs index 98d488a42..0b5627e19 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs @@ -75,7 +75,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Convert from screen to world space. Matrix4x4.Invert(this.TransformMatrix, out Matrix4x4 matrix); - const float Epsilon = 0.0000001F; if (this.Sampler is NearestNeighborResampler) { @@ -90,11 +89,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = 0; x < width; x++) { - var v3 = Vector3.Transform(new Vector3(x, y, 1), matrix); - - float z = MathF.Max(v3.Z, Epsilon); - int px = (int)MathF.Round(v3.X / z); - int py = (int)MathF.Round(v3.Y / z); + Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); + int px = (int)MathF.Round(point.X); + int py = (int)MathF.Round(point.Y); if (sourceRectangle.Contains(px, py)) { @@ -127,9 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { // Use the single precision position to calculate correct bounding pixels // otherwise we get rogue pixels outside of the bounds. - var v3 = Vector3.Transform(new Vector3(x, y, 1F), matrix); - Vector2 point = new Vector2(v3.X, v3.Y) / MathF.Max(v3.Z, Epsilon); - + Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs index 24b15d309..0ec8c8393 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs @@ -3,6 +3,7 @@ using System; using System.Numerics; +using System.Runtime.CompilerServices; using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.Transforms @@ -12,6 +13,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// internal static class TransformUtils { + /// + /// Applies the projective transform against the given coordinates flattened into the 2D space. + /// + /// The "x" vector coordinate. + /// The "y" vector coordinate. + /// The transform matrix. + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static Vector2 ProjectiveTransform2D(float x, float y, Matrix4x4 matrix) + { + const float Epsilon = 0.0000001F; + var v4 = Vector4.Transform(new Vector4(x, y, 0, 1F), matrix); + return new Vector2(v4.X, v4.Y) / MathF.Max(v4.W, Epsilon); + } + /// /// Creates a centered rotation matrix using the given rotation in degrees and the source size. /// @@ -94,12 +110,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { Matrix4x4 matrix = Matrix4x4.Identity; + /* + * SkMatrix is layed out in the following manner: + * + * [ ScaleX SkewY Persp0 ] + * [ SkewX ScaleY Persp1 ] + * [ TransX TransY Persp2 ] + * + * When converting from Matrix4x4 to SkMatrix, the third row and + * column is dropped. When converting from SkMatrix to Matrix4x4 + * the third row and column remain as identity: + * + * [ a b c ] [ a b 0 c ] + * [ d e f ] -> [ d e 0 f ] + * [ g h i ] [ 0 0 1 0 ] + * [ g h 0 i ] + */ switch (side) { case TaperSide.Left: matrix.M11 = fraction; matrix.M22 = fraction; - matrix.M13 = (fraction - 1) / size.Width; + matrix.M14 = (fraction - 1) / size.Width; switch (corner) { @@ -107,13 +139,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms break; case TaperCorner.LeftOrTop: - matrix.M12 = size.Height * matrix.M13; - matrix.M32 = size.Height * (1 - fraction); + matrix.M12 = size.Height * matrix.M14; + matrix.M42 = size.Height * (1 - fraction); break; case TaperCorner.Both: - matrix.M12 = size.Height * .5F * matrix.M13; - matrix.M32 = size.Height * (1 - fraction) / 2; + matrix.M12 = size.Height * .5F * matrix.M14; + matrix.M42 = size.Height * (1 - fraction) / 2; break; } @@ -122,7 +154,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms case TaperSide.Top: matrix.M11 = fraction; matrix.M22 = fraction; - matrix.M23 = (fraction - 1) / size.Height; + matrix.M24 = (fraction - 1) / size.Height; switch (corner) { @@ -130,13 +162,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms break; case TaperCorner.LeftOrTop: - matrix.M21 = size.Width * matrix.M23; - matrix.M31 = size.Width * (1 - fraction); + matrix.M21 = size.Width * matrix.M24; + matrix.M41 = size.Width * (1 - fraction); break; case TaperCorner.Both: - matrix.M21 = size.Width * .5F * matrix.M23; - matrix.M31 = size.Width * (1 - fraction) / 2; + matrix.M21 = size.Width * .5F * matrix.M24; + matrix.M41 = size.Width * (1 - fraction) * .5F; break; } @@ -144,7 +176,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms case TaperSide.Right: matrix.M11 = 1 / fraction; - matrix.M13 = (1 - fraction) / (size.Width * fraction); + matrix.M14 = (1 - fraction) / (size.Width * fraction); switch (corner) { @@ -152,11 +184,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms break; case TaperCorner.LeftOrTop: - matrix.M12 = size.Height * matrix.M13; + matrix.M12 = size.Height * matrix.M14; break; case TaperCorner.Both: - matrix.M12 = size.Height * .5F * matrix.M13; + matrix.M12 = size.Height * .5F * matrix.M14; break; } @@ -164,7 +196,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms case TaperSide.Bottom: matrix.M22 = 1 / fraction; - matrix.M23 = (1 - fraction) / (size.Height * fraction); + matrix.M24 = (1 - fraction) / (size.Height * fraction); switch (corner) { @@ -172,11 +204,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms break; case TaperCorner.LeftOrTop: - matrix.M21 = size.Width * matrix.M23; + matrix.M21 = size.Width * matrix.M24; break; case TaperCorner.Both: - matrix.M21 = size.Width * .5F * matrix.M23; + matrix.M21 = size.Width * .5F * matrix.M24; break; } @@ -260,17 +292,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return rectangle; } - Vector2 GetVector(float x, float y) - { - const float Epsilon = 0.0000001F; - var v3 = Vector3.Transform(new Vector3(x, y, 1F), matrix); - return new Vector2(v3.X, v3.Y) / MathF.Max(v3.Z, Epsilon); - } - - Vector2 tl = GetVector(rectangle.Left, rectangle.Top); - Vector2 tr = GetVector(rectangle.Right, rectangle.Top); - Vector2 bl = GetVector(rectangle.Left, rectangle.Bottom); - Vector2 br = GetVector(rectangle.Right, rectangle.Bottom); + Vector2 tl = ProjectiveTransform2D(rectangle.Left, rectangle.Top, matrix); + Vector2 tr = ProjectiveTransform2D(rectangle.Right, rectangle.Top, matrix); + Vector2 bl = ProjectiveTransform2D(rectangle.Left, rectangle.Bottom, matrix); + Vector2 br = ProjectiveTransform2D(rectangle.Right, rectangle.Bottom, matrix); return GetBoundingRectangle(tl, tr, bl, br); } diff --git a/src/Shared/AssemblyInfo.Common.cs b/src/Shared/AssemblyInfo.Common.cs index 327d3abd7..82e1dac6c 100644 --- a/src/Shared/AssemblyInfo.Common.cs +++ b/src/Shared/AssemblyInfo.Common.cs @@ -5,32 +5,6 @@ using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyDescription("A cross-platform library for processing of image files; written in C#")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Six Labors")] -[assembly: AssemblyProduct("SixLabors.ImageSharp")] -[assembly: AssemblyCopyright("Copyright (c) Six Labors and contributors.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] -[assembly: AssemblyInformationalVersion("1.0.0.0")] - // Ensure the internals can be built and tested. [assembly: InternalsVisibleTo("SixLabors.ImageSharp.Drawing")] [assembly: InternalsVisibleTo("ImageSharp.Benchmarks")] diff --git a/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs b/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs index 9ddfad722..94349b20b 100644 --- a/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs +++ b/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs @@ -1,5 +1,4 @@ using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Attributes.Jobs; namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath { diff --git a/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs b/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs index 5c2fe81fa..d5683673f 100644 --- a/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs +++ b/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs @@ -1,5 +1,4 @@ using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Attributes.Jobs; namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath { diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs index a8fea6866..3b288260c 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs @@ -4,7 +4,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Attributes.Jobs; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tuples; diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index a705c9bac..f941203db 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -16,7 +16,7 @@ - + diff --git a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj index 4d7b7de75..cb286cc28 100644 --- a/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj +++ b/tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj @@ -18,19 +18,13 @@ - - - - + - - - \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 5f2de9f51..251475567 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -55,6 +55,30 @@ namespace SixLabors.ImageSharp.Tests } } + [Theory] + [WithFile(WinBmpv2, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecodeBmpv2(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider, "png"); + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFile(Bit8Palette4, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode4BytePerEntryPalette(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage(new BmpDecoder())) + { + image.DebugSave(provider, "png"); + image.CompareToOriginal(provider); + } + } + [Theory] [InlineData(Car, 24)] [InlineData(F, 24)] @@ -89,18 +113,17 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [MemberData(nameof(RatioFiles))] - public void Identify_VerifyRatio(string imagePath, int xResolution, int yResolution, PixelResolutionUnit resolutionUnit) + [WithFile(Os2v2Short, PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_Os2v2XShortHeader(TestImageProvider provider) + where TPixel : struct, IPixel { - var testFile = TestFile.Create(imagePath); - using (var stream = new MemoryStream(testFile.Bytes, false)) + using (Image image = provider.GetImage(new BmpDecoder())) { - var decoder = new BmpDecoder(); - IImageInfo image = decoder.Identify(Configuration.Default, stream); - ImageMetaData meta = image.MetaData; - Assert.Equal(xResolution, meta.HorizontalResolution); - Assert.Equal(yResolution, meta.VerticalResolution); - Assert.Equal(resolutionUnit, meta.ResolutionUnits); + image.DebugSave(provider, "png"); + + // TODO: Neither System.Drawing not MagickReferenceDecoder + // can correctly decode this file. + // image.CompareToOriginal(provider); } } } diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 86c1a7a25..7452d6e49 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -28,15 +28,12 @@ - - - - - + + diff --git a/tests/ImageSharp.Tests/Primitives/DenseMatrixTests.cs b/tests/ImageSharp.Tests/Primitives/DenseMatrixTests.cs index fa4862293..0af8ae45f 100644 --- a/tests/ImageSharp.Tests/Primitives/DenseMatrixTests.cs +++ b/tests/ImageSharp.Tests/Primitives/DenseMatrixTests.cs @@ -106,5 +106,29 @@ namespace SixLabors.ImageSharp.Tests.Primitives Assert.Equal(0, dense.Data[i]); } } + + [Fact] + public void DenseMatrixCorrectlyCasts() + { + float[,] actual = new DenseMatrix(FloydSteinbergMatrix); + Assert.Equal(FloydSteinbergMatrix, actual); + } + + [Fact] + public void DenseMatrixCanTranspose() + { + var dense = new DenseMatrix(3, 1); + dense[0, 0] = 1; + dense[0, 1] = 2; + dense[0, 2] = 3; + + DenseMatrix transposed = dense.Transpose(); + + Assert.Equal(dense.Columns, transposed.Rows); + Assert.Equal(dense.Rows, transposed.Columns); + Assert.Equal(1, transposed[0, 0]); + Assert.Equal(2, transposed[1, 0]); + Assert.Equal(3, transposed[2, 0]); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs index 08b294913..5d3790f07 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs @@ -208,10 +208,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms { var result = new TheoryData(); - string[] resamplerNames = typeof(KnownResamplers).GetProperties(BindingFlags.Public | BindingFlags.Static) - .Select(p => p.Name) - .Where(name => name != nameof(KnownResamplers.NearestNeighbor)) - .ToArray(); + string[] resamplerNames = TestUtils.GetAllResamplerNames(false); int[] dimensionVals = { diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index b4aff53e8..034b66ae9 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -20,42 +20,82 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public static readonly string[] CommonTestImages = { TestImages.Png.CalliphoraPartial }; private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); - - public static readonly TheoryData AllResamplers = - new TheoryData + + public static readonly string[] AllResamplerNames = TestUtils.GetAllResamplerNames(); + + public static readonly string[] SmokeTestResamplerNames = { - { "Bicubic", KnownResamplers.Bicubic }, - { "Triangle", KnownResamplers.Triangle}, - { "NearestNeighbor", KnownResamplers.NearestNeighbor }, - { "Box", KnownResamplers.Box }, - // { "Lanczos2", KnownResamplers.Lanczos2 }, TODO: Add expected file - { "Lanczos3", KnownResamplers.Lanczos3 }, - { "Lanczos5", KnownResamplers.Lanczos5 }, - { "MitchellNetravali", KnownResamplers.MitchellNetravali }, - { "Lanczos8", KnownResamplers.Lanczos8 }, - { "Hermite", KnownResamplers.Hermite }, - { "Spline", KnownResamplers.Spline }, - { "Robidoux", KnownResamplers.Robidoux }, - { "RobidouxSharp", KnownResamplers.RobidouxSharp }, - { "Welch", KnownResamplers.Welch } + nameof(KnownResamplers.NearestNeighbor), + nameof(KnownResamplers.Bicubic), + nameof(KnownResamplers.Box), + nameof(KnownResamplers.Lanczos5), }; [Theory] - [WithTestPatternImages(nameof(AllResamplers), 100, 100, DefaultPixelType, 0.5f)] - [WithFileCollection(nameof(CommonTestImages), nameof(AllResamplers), DefaultPixelType, 0.5f)] - [WithFileCollection(nameof(CommonTestImages), nameof(AllResamplers), DefaultPixelType, 0.3f)] - public void Resize_WorksWithAllResamplers(TestImageProvider provider, string name, IResampler sampler, float ratio) + [WithFileCollection(nameof(CommonTestImages), nameof(AllResamplerNames), DefaultPixelType, 0.5f, null, null)] + [WithFileCollection(nameof(CommonTestImages), nameof(SmokeTestResamplerNames), DefaultPixelType, 0.3f, null, null)] + [WithFileCollection(nameof(CommonTestImages), nameof(SmokeTestResamplerNames), DefaultPixelType, 1.8f, null, null)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 100, 100, DefaultPixelType, 0.5f, null, null)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 100, 100, DefaultPixelType, 1f, null, null)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 50, 50, DefaultPixelType, 8f, null, null)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 201, 199, DefaultPixelType, null, 100, 99)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 301, 1180, DefaultPixelType, null, 300, 480)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 49, 80, DefaultPixelType, null, 301, 100)] + public void Resize_WorksWithAllResamplers( + TestImageProvider provider, + string samplerName, + float? ratio, + int? specificDestWidth, + int? specificDestHeight) where TPixel : struct, IPixel { - using (Image image = provider.GetImage()) - { - SizeF newSize = image.Size() * ratio; - image.Mutate(x => x.Resize((Size)newSize, sampler, false)); - FormattableString details = $"{name}-{ratio.ToString(System.Globalization.CultureInfo.InvariantCulture)}"; + IResampler sampler = TestUtils.GetResampler(samplerName); - image.DebugSave(provider, details); - image.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.02f), provider, details); - } + // NeirestNeighbourResampler is producing slightly different results With classic .NET framework on 32bit + // most likely because of differences in numeric behavior. + // The difference is well visible when comparing output for + // Resize_WorksWithAllResamplers_TestPattern301x1180_NearestNeighbor-300x480.png + // TODO: Should we investigate this? + bool allowHigherInaccuracy = !TestEnvironment.Is64BitProcess + && string.IsNullOrEmpty(TestEnvironment.NetCoreVersion) + && sampler is NearestNeighborResampler; + + var comparer = ImageComparer.TolerantPercentage(allowHigherInaccuracy ? 0.3f : 0.017f); + + provider.RunValidatingProcessorTest( + ctx => + { + + SizeF newSize; + string destSizeInfo; + if (ratio.HasValue) + { + newSize = ctx.GetCurrentSize() * ratio.Value; + destSizeInfo = ratio.Value.ToString(System.Globalization.CultureInfo.InvariantCulture); + } + else + { + if (!specificDestWidth.HasValue || !specificDestHeight.HasValue) + { + throw new InvalidOperationException( + "invalid dimensional input for Resize_WorksWithAllResamplers!"); + } + + newSize = new SizeF(specificDestWidth.Value, specificDestHeight.Value); + destSizeInfo = $"{newSize.Width}x{newSize.Height}"; + } + + FormattableString testOutputDetails = $"{samplerName}-{destSizeInfo}"; + ctx.Apply( + img => img.DebugSave( + provider, + $"{testOutputDetails}-ORIGINAL", + appendPixelTypeToFileName: false)); + ctx.Resize((Size)newSize, sampler, false); + return testOutputDetails; + }, + comparer, + appendPixelTypeToFileName: false); } [Theory] diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs index 1da660d22..056f66af7 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ProjectiveTransformTests.cs @@ -111,7 +111,32 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms using (Image image = provider.GetImage()) { Matrix4x4 matrix = Matrix4x4.Identity; - matrix.M13 = 0.01F; + matrix.M14 = 0.01F; + + ProjectiveTransformBuilder builder = new ProjectiveTransformBuilder() + .AppendMatrix(matrix); + + image.Mutate(i => i.Transform(builder)); + + image.DebugSave(provider); + image.CompareToReferenceOutput(TolerantComparer, provider); + } + } + + [Theory] + [WithSolidFilledImages(290, 154, 0, 0, 255, PixelTypes.Rgba32)] + public void PerspectiveTransformMatchesCSS(TestImageProvider provider) + where TPixel : struct, IPixel + { + // https://jsfiddle.net/dFrHS/545/ + // https://github.com/SixLabors/ImageSharp/issues/787 + using (Image image = provider.GetImage()) + { + var matrix = new Matrix4x4( + 0.260987f, -0.434909f, 0, -0.0022184f, + 0.373196f, 0.949882f, 0, -0.000312129f, + 0, 0, 1, 0, + 52, 165, 0, 1); ProjectiveTransformBuilder builder = new ProjectiveTransformBuilder() .AppendMatrix(matrix); diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 46f9459c5..6141e9e2a 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -203,6 +203,11 @@ namespace SixLabors.ImageSharp.Tests public const string Bit16 = "Bmp/test16.bmp"; public const string Bit16Inverted = "Bmp/test16-inverted.bmp"; public const string Bit32Rgb = "Bmp/rgb32.bmp"; + + // Note: This format can be called OS/2 BMPv1, or Windows BMPv2 + public const string WinBmpv2 = "Bmp/pal8os2v1_winv2.bmp"; + public const string Bit8Palette4 = "Bmp/pal8-0.bmp"; + public const string Os2v2Short = "Bmp/pal8os2v2-16.bmp"; public static readonly string[] All = { diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/ImageDataAttributeBase.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/ImageDataAttributeBase.cs index ec3254921..6107154d0 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Attributes/ImageDataAttributeBase.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/ImageDataAttributeBase.cs @@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Tests addedRows = memberItems.Select(x => x as object[]); if (addedRows.Any(x => x == null)) { - throw new ArgumentException($"Property {this.MemberName} on {this.MemberType ?? testMethod.DeclaringType} yielded an item that is not an object[]"); + addedRows = memberItems.Select(x => new[] { x }); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs index cc09dc057..17e5369d4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestPatternProvider.cs @@ -16,10 +16,9 @@ namespace SixLabors.ImageSharp.Tests /// /// A test image provider that produces test patterns. /// - /// private class TestPatternProvider : BlankProvider { - static Dictionary> testImages = new Dictionary>(); + static readonly Dictionary> TestImages = new Dictionary>(); public TestPatternProvider(int width, int height) : base(width, height) @@ -35,17 +34,17 @@ namespace SixLabors.ImageSharp.Tests public override Image GetImage() { - lock (testImages) + lock (TestImages) { - if (!testImages.ContainsKey(this.SourceFileOrDescription)) + if (!TestImages.ContainsKey(this.SourceFileOrDescription)) { Image image = new Image(this.Width, this.Height); DrawTestPattern(image); - testImages.Add(this.SourceFileOrDescription, image); + TestImages.Add(this.SourceFileOrDescription, image); } } - return testImages[this.SourceFileOrDescription].Clone(); + return TestImages[this.SourceFileOrDescription].Clone(); } /// @@ -202,6 +201,7 @@ namespace SixLabors.ImageSharp.Tests Rgba32 t = new Rgba32(0); for (int x = left; x < right; x++) + { for (int y = top; y < bottom; y++) { t.PackedValue += stepsPerPixel; @@ -210,6 +210,7 @@ namespace SixLabors.ImageSharp.Tests c.FromVector4(v); pixels[x, y] = c; } + } } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index 334b6552a..7d0684722 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -34,8 +34,7 @@ namespace SixLabors.ImageSharp.Tests { string extension = Path.GetExtension(filePath); - IImageFormat format = Configuration.ImageFormatsManager.FindFormatByFileExtension(extension); - return format; + return Configuration.ImageFormatsManager.FindFormatByFileExtension(extension); } private static void ConfigureCodecs( @@ -69,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests cfg.ConfigureCodecs( BmpFormat.Instance, - SystemDrawingReferenceDecoder.Instance, + IsWindows ? (IImageDecoder)SystemDrawingReferenceDecoder.Instance : MagickReferenceDecoder.Instance, bmpEncoder, new BmpImageFormatDetector()); diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index 5ea0bccf0..e51aa28d8 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -193,6 +193,45 @@ namespace SixLabors.ImageSharp.Tests } } + internal static void RunValidatingProcessorTest( + this TestImageProvider provider, + Func, FormattableString> processAndGetTestOutputDetails, + ImageComparer comparer = null, + bool appendPixelTypeToFileName = true, + bool appendSourceFileOrDescription = true) + where TPixel : struct, IPixel + { + if (comparer == null) + { + comparer = ImageComparer.TolerantPercentage(0.001f); + } + + using (Image image = provider.GetImage()) + { + FormattableString testOutputDetails = $""; + image.Mutate( + ctx => { testOutputDetails = processAndGetTestOutputDetails(ctx); } + ); + + image.DebugSave( + provider, + testOutputDetails, + appendPixelTypeToFileName: appendPixelTypeToFileName, + appendSourceFileOrDescription: appendSourceFileOrDescription); + + // TODO: Investigate the cause of pixel inaccuracies under Linux + if (TestEnvironment.IsWindows) + { + image.CompareToReferenceOutput( + comparer, + provider, + testOutputDetails, + appendPixelTypeToFileName: appendPixelTypeToFileName, + appendSourceFileOrDescription: appendSourceFileOrDescription); + } + } + } + public static void RunValidatingProcessorTestOnWrappedMemoryImage( this TestImageProvider provider, Action> process, @@ -297,5 +336,13 @@ namespace SixLabors.ImageSharp.Tests return (IResampler)property.GetValue(null); } + + public static string[] GetAllResamplerNames(bool includeNearestNeighbour = true) + { + return typeof(KnownResamplers).GetProperties(BindingFlags.Public | BindingFlags.Static) + .Select(p => p.Name) + .Where(name => includeNearestNeighbour || name != nameof(KnownResamplers.NearestNeighbor)) + .ToArray(); + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs index 30bb16c2a..122234ae8 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs @@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.Tests [Theory] [InlineData("lol/foo.png", typeof(MagickReferenceDecoder))] - [InlineData("lol/Rofl.bmp", typeof(SystemDrawingReferenceDecoder))] + [InlineData("lol/Rofl.bmp", typeof(MagickReferenceDecoder))] [InlineData("lol/Baz.JPG", typeof(JpegDecoder))] [InlineData("lol/Baz.gif", typeof(GifDecoder))] public void GetReferenceDecoder_ReturnsCorrectDecoders_Linux(string fileName, Type expectedDecoderType) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index a8140e39d..cac7828e9 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -9,6 +9,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using Xunit; using Xunit.Abstractions; +// ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests { @@ -313,6 +314,17 @@ namespace SixLabors.ImageSharp.Tests } + [Theory] + [WithTestPatternImages(49,20, PixelTypes.Rgba32)] + public void Use_WithTestPatternImages(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image img = provider.GetImage()) + { + img.DebugSave(provider); + } + } + public static readonly TheoryData BasicData = new TheoryData() { TestImageProvider.Blank(10, 20), diff --git a/tests/Images/External b/tests/Images/External index 5b18d8c95..69603ee5b 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 5b18d8c95acffb773012881870ba6f521ba13128 +Subproject commit 69603ee5b6f7dd64114fc44d321e50d9b2d439be diff --git a/tests/Images/Input/Bmp/pal8-0.bmp b/tests/Images/Input/Bmp/pal8-0.bmp new file mode 100644 index 000000000..a5565d59f --- /dev/null +++ b/tests/Images/Input/Bmp/pal8-0.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ae0f808fea31352b8667fdaf897d057c7e02483c43d43cd735f92f4f149fe8d +size 9270 diff --git a/tests/Images/Input/Bmp/pal8os2v1_winv2.bmp b/tests/Images/Input/Bmp/pal8os2v1_winv2.bmp new file mode 100644 index 000000000..42440b6df --- /dev/null +++ b/tests/Images/Input/Bmp/pal8os2v1_winv2.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2bfe739377020722872f7fa3ba3ff3ff0daa17f2f202c80e25cf66c4ec30e506 +size 8986 diff --git a/tests/Images/Input/Bmp/pal8os2v2-16.bmp b/tests/Images/Input/Bmp/pal8os2v2-16.bmp new file mode 100644 index 000000000..7cc99c56f --- /dev/null +++ b/tests/Images/Input/Bmp/pal8os2v2-16.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8085c60533095d9a756009f84c050d01605fc029a980a13d1bdabe943c50de5a +size 9246