Browse Source

Merge remote-tracking branch 'upstream/master' into jpeg-12bit

af/merge-core
James Jackson-South 7 years ago
parent
commit
8f014e0ac1
  1. 20
      src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
  2. 47
      src/ImageSharp/Advanced/AotCompilerTools.cs
  3. 8
      src/ImageSharp/ColorSpaces/CieLab.cs
  4. 5
      src/ImageSharp/ColorSpaces/CieLch.cs
  5. 8
      src/ImageSharp/ColorSpaces/CieLchuv.cs
  6. 8
      src/ImageSharp/ColorSpaces/CieLuv.cs
  7. 2
      src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
  8. 7
      src/ImageSharp/ColorSpaces/CieXyy.cs
  9. 7
      src/ImageSharp/ColorSpaces/CieXyz.cs
  10. 8
      src/ImageSharp/ColorSpaces/Cmyk.cs
  11. 10
      src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs
  12. 10
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/GammaWorkingSpace.cs
  13. 5
      src/ImageSharp/ColorSpaces/Conversion/Implementation/WorkingSpaces/RgbWorkingSpaceBase.cs
  14. 7
      src/ImageSharp/ColorSpaces/Hsl.cs
  15. 7
      src/ImageSharp/ColorSpaces/Hsv.cs
  16. 5
      src/ImageSharp/ColorSpaces/HunterLab.cs
  17. 7
      src/ImageSharp/ColorSpaces/LinearRgb.cs
  18. 7
      src/ImageSharp/ColorSpaces/Lms.cs
  19. 7
      src/ImageSharp/ColorSpaces/Rgb.cs
  20. 7
      src/ImageSharp/ColorSpaces/YCbCr.cs
  21. 9
      src/ImageSharp/Common/Helpers/TolerantMath.cs
  22. 4
      src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs
  23. 34
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  24. 24
      src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
  25. 12
      src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs
  26. 13
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
  27. 4
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  28. 2
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  29. 22
      src/ImageSharp/ImageSharp.csproj
  30. 14
      src/ImageSharp/MetaData/ImageProperty.cs
  31. 6
      src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs
  32. 20
      src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
  33. 21
      src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs
  34. 11
      src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs
  35. 8
      src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs
  36. 11
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs
  37. 5
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs
  38. 5
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs
  39. 17
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs
  40. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs
  41. 11
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs
  42. 5
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs
  43. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs
  44. 24
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs
  45. 24
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs
  46. 28
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs
  47. 28
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs
  48. 17
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs
  49. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs
  50. 13
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs
  51. 18
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs
  52. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs
  53. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs
  54. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs
  55. 11
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs
  56. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs
  57. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs
  58. 17
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs
  59. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs
  60. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs
  61. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs
  62. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs
  63. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs
  64. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs
  65. 13
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs
  66. 8
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs
  67. 13
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs
  68. 15
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs
  69. 13
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs
  70. 26
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs
  71. 10
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs
  72. 24
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileDescription.cs
  73. 13
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs
  74. 12
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs
  75. 15
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs
  76. 8
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs
  77. 14
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs
  78. 7
      src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs
  79. 7
      src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
  80. 7
      src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs
  81. 7
      src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs
  82. 33
      src/ImageSharp/Primitives/DenseMatrix{T}.cs
  83. 7
      src/ImageSharp/Primitives/ValueSize.cs
  84. 18
      src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs
  85. 51
      src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs
  86. 86
      src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs
  87. 2
      src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs
  88. 3
      src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs
  89. 13
      src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
  90. 79
      src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs
  91. 26
      src/Shared/AssemblyInfo.Common.cs
  92. 1
      tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs
  93. 1
      tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs
  94. 1
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_Rgba32_To_Bgra32.cs
  95. 2
      tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
  96. 8
      tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj
  97. 43
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
  98. 7
      tests/ImageSharp.Tests/ImageSharp.Tests.csproj
  99. 24
      tests/ImageSharp.Tests/Primitives/DenseMatrixTests.cs
  100. 5
      tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs

20
src/ImageSharp.Drawing/ImageSharp.Drawing.csproj

@ -1,10 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>An extension to ImageSharp that allows the drawing of images, paths, and text.</Description>
<PropertyGroup>
<AssemblyTitle>SixLabors.ImageSharp.Drawing</AssemblyTitle>
<Authors>SixLabors and contributors</Authors>
<Company>Six Labors</Company>
<Copyright>Copyright (c) Six Labors and contributors.</Copyright>
<Product>SixLabors.ImageSharp</Product>
<Description>An extension to ImageSharp that allows the drawing of images, paths, and text.</Description>
<NeutralLanguage>en</NeutralLanguage>
<VersionPrefix Condition="$(packageversion) != ''">$(packageversion)</VersionPrefix>
<VersionPrefix Condition="$(packageversion) == ''">0.0.1</VersionPrefix>
<Authors>SixLabors and contributors</Authors>
<TargetFrameworks>netstandard1.3;netstandard2.0</TargetFrameworks>
<LangVersion>7.3</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -17,15 +22,6 @@
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/SixLabors/ImageSharp</RepositoryUrl>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateNeutralResourcesLanguageAttribute>false</GenerateNeutralResourcesLanguageAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<DebugType Condition="$(codecov) != ''">full</DebugType>
<DebugType Condition="$(codecov) == ''">portable</DebugType>
<DebugSymbols>True</DebugSymbols>

47
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
/// </summary>
public static class AotCompilerTools
{
static AotCompilerTools()
{
System.Runtime.CompilerServices.Unsafe.SizeOf<long>();
System.Runtime.CompilerServices.Unsafe.SizeOf<short>();
System.Runtime.CompilerServices.Unsafe.SizeOf<float>();
System.Runtime.CompilerServices.Unsafe.SizeOf<double>();
System.Runtime.CompilerServices.Unsafe.SizeOf<byte>();
System.Runtime.CompilerServices.Unsafe.SizeOf<Block8x8>();
System.Runtime.CompilerServices.Unsafe.SizeOf<Vector4>();
}
/// <summary>
/// Seeds the compiler using the given pixel format.
/// </summary>
@ -27,6 +41,13 @@ namespace SixLabors.ImageSharp.Advanced
AotCompileWuQuantizer<TPixel>();
AotCompileDithering<TPixel>();
System.Runtime.CompilerServices.Unsafe.SizeOf<TPixel>();
AotCodec<TPixel>(new Formats.Png.PngDecoder(), new Formats.Png.PngEncoder());
AotCodec<TPixel>(new Formats.Bmp.BmpDecoder(), new Formats.Bmp.BmpEncoder());
AotCodec<TPixel>(new Formats.Gif.GifDecoder(), new Formats.Gif.GifEncoder());
AotCodec<TPixel>(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<TPixel>(new ImageFrame<TPixel>(Configuration.Default, 1, 1), pixel, pixel, 0, 0, 0, 0, 0, 0);
}
/// <summary>
/// This method pre-seeds the decoder and encoder for a given pixel format in the AoT compiler for iOS.
/// </summary>
/// <param name="decoder">The image decoder to seed.</param>
/// <param name="encoder">The image encoder to seed.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
private static void AotCodec<TPixel>(IImageDecoder decoder, IImageEncoder encoder)
where TPixel : struct, IPixel<TPixel>
{
try
{
decoder.Decode<TPixel>(Configuration.Default, null);
}
catch
{
}
try
{
encoder.Encode<TPixel>(null, null);
}
catch
{
}
}
}
}

8
src/ImageSharp/ColorSpaces/CieLab.cs

@ -118,13 +118,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public static bool operator !=(CieLab left, CieLab right) => !left.Equals(right);
/// <inheritdoc/>
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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"CieLab({this.L:#0.##}, {this.A:#0.##}, {this.B:#0.##})");

5
src/ImageSharp/ColorSpaces/CieLch.cs

@ -122,10 +122,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
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);
}
/// <inheritdoc/>

8
src/ImageSharp/ColorSpaces/CieLchuv.cs

@ -119,13 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public static bool operator !=(CieLchuv left, CieLchuv right) => !left.Equals(right);
/// <inheritdoc/>
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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"CieLchuv({this.L:#0.##}, {this.C:#0.##}, {this.H:#0.##})");

8
src/ImageSharp/ColorSpaces/CieLuv.cs

@ -119,13 +119,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public static bool operator !=(CieLuv left, CieLuv right) => !left.Equals(right);
/// <inheritdoc/>
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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"CieLuv({this.L:#0.##}, {this.U:#0.##}, {this.V:#0.##})");

2
src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs

@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc />
[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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"CieXyChromaticityCoordinates({this.X:#0.##}, {this.Y:#0.##})");

7
src/ImageSharp/ColorSpaces/CieXyy.cs

@ -83,12 +83,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public static bool operator !=(CieXyy left, CieXyy right) => !left.Equals(right);
/// <inheritdoc/>
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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"CieXyy({this.X:#0.##}, {this.Y:#0.##}, {this.Yl:#0.##})");

7
src/ImageSharp/ColorSpaces/CieXyz.cs

@ -86,12 +86,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public Vector3 ToVector3() => new Vector3(this.X, this.Y, this.Z);
/// <inheritdoc/>
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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"CieXyz({this.X:#0.##}, {this.Y:#0.##}, {this.Z:#0.##})");

8
src/ImageSharp/ColorSpaces/Cmyk.cs

@ -90,13 +90,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"Cmyk({this.C:#0.##}, {this.M:#0.##}, {this.Y:#0.##}, {this.K:#0.##})");

10
src/ImageSharp/ColorSpaces/Conversion/Implementation/RGBPrimariesChromaticityCoordinates.cs

@ -86,14 +86,6 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
}
/// <inheritdoc />
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);
}
}

10
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
}
/// <inheritdoc/>
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);
}
}

5
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
{
/// <summary>
@ -76,8 +78,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
/// <inheritdoc/>
public override int GetHashCode()
{
int hash = this.WhitePoint.GetHashCode();
return HashHelpers.Combine(hash, this.ChromaticityCoordinates.GetHashCode());
return HashCode.Combine(this.WhitePoint, this.ChromaticityCoordinates);
}
}
}

7
src/ImageSharp/ColorSpaces/Hsl.cs

@ -84,12 +84,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"Hsl({this.H:#0.##}, {this.S:#0.##}, {this.L:#0.##})");

7
src/ImageSharp/ColorSpaces/Hsv.cs

@ -82,12 +82,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"Hsv({this.H:#0.##}, {this.S:#0.##}, {this.V:#0.##})");

5
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);
}
/// <inheritdoc/>

7
src/ImageSharp/ColorSpaces/LinearRgb.cs

@ -126,12 +126,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"LinearRgb({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##})");

7
src/ImageSharp/ColorSpaces/Lms.cs

@ -87,12 +87,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public Vector3 ToVector3() => new Vector3(this.L, this.M, this.S);
/// <inheritdoc/>
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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"Lms({this.L:#0.##}, {this.M:#0.##}, {this.S:#0.##})");

7
src/ImageSharp/ColorSpaces/Rgb.cs

@ -147,12 +147,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
public Vector3 ToVector3() => new Vector3(this.R, this.G, this.B);
/// <inheritdoc/>
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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"Rgb({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##})");

7
src/ImageSharp/ColorSpaces/YCbCr.cs

@ -83,12 +83,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// <inheritdoc/>
[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);
/// <inheritdoc/>
public override string ToString() => FormattableString.Invariant($"YCbCr({this.Y}, {this.Cb}, {this.Cr})");

9
src/ImageSharp/Common/Helpers/TolerantMath.cs

@ -16,6 +16,13 @@ namespace SixLabors.ImageSharp
private readonly double negEpsilon;
/// <summary>
/// A read-only default instance for <see cref="TolerantMath"/> 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!
/// </summary>
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);
/// <summary>
/// <paramref name="a"/> == 0
/// </summary>

4
src/ImageSharp/Common/ParallelUtils/ParallelHelper.cs

@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.ParallelUtils
Rectangle rectangle,
in ParallelExecutionSettings parallelSettings,
Action<RowInterval, Memory<T>> 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<RowInterval, Memory<T>> body)
where T : struct
where T : unmanaged
{
IterateRowsWithTempBuffer(rectangle, configuration.GetParallelSettings(), body);
}

34
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<TPixel>(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
/// <param name="colors">The <see cref="T:byte[]"/> containing the colors.</param>
/// <param name="width">The width of the bitmap.</param>
/// <param name="height">The height of the bitmap.</param>
/// <param name="bits">The number of bits per pixel.</param>
/// <param name="bitsPerPixel">The number of bits per pixel.</param>
/// <param name="bytesPerColorMapEntry">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.</param>
/// <param name="inverted">Whether the bitmap is inverted.</param>
private void ReadRgbPalette<TPixel>(Buffer2D<TPixel> pixels, byte[] colors, int width, int height, int bits, bool inverted)
private void ReadRgbPalette<TPixel>(Buffer2D<TPixel> pixels, byte[] colors, int width, int height, int bitsPerPixel, int bytesPerColorMapEntry, bool inverted)
where TPixel : struct, IPixel<TPixel>
{
// 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<byte, Bgr24>(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
/// <summary>
/// Reads the <see cref="BmpFileHeader"/> and <see cref="BmpInfoHeader"/> from the stream and sets the corresponding fields.
/// </summary>
private void ReadImageHeaders(Stream stream, out bool inverted, out byte[] palette)
/// <returns>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.</returns>
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;
}
}
}

24
src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs

@ -26,6 +26,11 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// </summary>
public const int CoreSize = 12;
/// <summary>
/// Defines the size of the short variant of the OS22XBITMAPHEADER data structure in the bitmap file.
/// </summary>
public const int Os22ShortSize = 16;
/// <summary>
/// Defines the size of the biggest supported header data structure in the bitmap file.
/// </summary>
@ -143,7 +148,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
/// <summary>
/// Parses the BITMAPCOREHEADER consisting of the headerSize, width, height, planes, and bitsPerPixel fields (12 bytes).
/// </summary>
/// <param name="data">The data to parse,</param>
/// <param name="data">The data to parse.</param>
/// <returns>Parsed header</returns>
/// <seealso href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd183372.aspx"/>
public static BmpInfoHeader ParseCore(ReadOnlySpan<byte> data)
@ -156,6 +161,23 @@ namespace SixLabors.ImageSharp.Formats.Bmp
bitsPerPixel: BinaryPrimitives.ReadInt16LittleEndian(data.Slice(10, 2)));
}
/// <summary>
/// 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.
/// </summary>
/// <param name="data">The data to parse.</param>
/// <returns>Parsed header</returns>
/// <seealso href="https://www.fileformat.info/format/os2bmp/egff.htm"/>
public static BmpInfoHeader ParseOs22Short(ReadOnlySpan<byte> 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<byte> buffer)
{
ref BmpInfoHeader dest = ref Unsafe.As<byte, BmpInfoHeader>(ref MemoryMarshal.GetReference(buffer));

12
src/ImageSharp/Formats/Jpeg/Components/Decoder/AdobeMarker.cs

@ -100,13 +100,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// <inheritdoc/>
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);
}
}
}

13
src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs

@ -112,13 +112,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// <inheritdoc/>
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);
}
}
}

4
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());
}
}
}

2
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));
}

22
src/ImageSharp/ImageSharp.csproj

@ -1,10 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>A cross-platform library for the processing of image files; written in C#</Description>
<AssemblyTitle>SixLabors.ImageSharp</AssemblyTitle>
<Authors>Six Labors and contributors</Authors>
<Company>Six Labors</Company>
<Copyright>Copyright (c) Six Labors and contributors.</Copyright>
<Product>SixLabors.ImageSharp</Product>
<Description>A cross-platform library for the processing of image files; written in C#</Description>
<NeutralLanguage>en</NeutralLanguage>
<VersionPrefix Condition="$(packageversion) != ''">$(packageversion)</VersionPrefix>
<VersionPrefix Condition="$(packageversion) == ''">0.0.1</VersionPrefix>
<Authors>Six Labors and contributors</Authors>
<TargetFrameworks>netstandard1.3;netstandard2.0;netcoreapp2.1;net472</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@ -16,20 +21,11 @@
<PackageLicenseUrl>http://www.apache.org/licenses/LICENSE-2.0</PackageLicenseUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/SixLabors/ImageSharp</RepositoryUrl>
<GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateNeutralResourcesLanguageAttribute>false</GenerateNeutralResourcesLanguageAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<DebugType Condition="$(codecov) != ''">full</DebugType>
<DebugType Condition="$(codecov) == ''">portable</DebugType>
<DebugSymbols>True</DebugSymbols>
<Features>IOperation</Features>
<LangVersion>Latest</LangVersion>
<LangVersion>7.3</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1' OR '$(TargetFramework)' == 'net472' ">
@ -42,7 +38,7 @@
<ItemGroup>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.1" />
<PackageReference Include="SixLabors.Core" Version="1.0.0-dev000089" />
<PackageReference Include="SixLabors.Core" Version="1.0.0-dev000094" />
<AdditionalFiles Include="..\..\stylecop.json" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta007">
<PrivateAssets>All</PrivateAssets>

14
src/ImageSharp/MetaData/ImageProperty.cs

@ -99,19 +99,7 @@ namespace SixLabors.ImageSharp.MetaData
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
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);
/// <summary>
/// Returns the fully qualified type name of this instance.

6
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<TDataType>(ReadOnlySpan<byte> 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<ExifTag>();
}

20
src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs

@ -198,7 +198,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
}
/// <inheritdoc/>
public override int GetHashCode() => this.GetHashCode(this);
public override int GetHashCode()
{
return HashCode.Combine(this.Tag, this.DataType, this.Value);
}
/// <inheritdoc/>
public override string ToString()
@ -714,20 +717,5 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
throw new NotSupportedException();
}
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <param name="exif">
/// The instance of <see cref="ExifValue"/> to return the hash code for.
/// </param>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
private int GetHashCode(ExifValue exif)
{
int hashCode = exif.Tag.GetHashCode() ^ exif.DataType.GetHashCode();
return hashCode ^ exif.Value?.GetHashCode() ?? hashCode;
}
}
}

21
src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs

@ -154,18 +154,15 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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());
}
}
}

11
src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs

@ -73,13 +73,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
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)

8
src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs

@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (int)this.Signature * 397;
}
}
public override int GetHashCode() => this.Signature.GetHashCode();
}
}

11
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs

@ -110,13 +110,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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)

5
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs

@ -70,10 +70,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.ColorantNumber?.GetHashCode() ?? 0);
}
return HashCode.Combine(this.Signature, this.ColorantNumber);
}
}
}

5
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs

@ -72,10 +72,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.ColorantData?.GetHashCode() ?? 0);
}
return HashCode.Combine(this.Signature, this.ColorantData);
}
}
}

17
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs

@ -121,16 +121,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs

@ -116,12 +116,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.CurveData?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.CurveData);
}
}

11
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs

@ -91,13 +91,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
}
}

5
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs

@ -66,10 +66,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ this.Value.GetHashCode();
}
return HashCode.Combine(this.Signature, this.Value);
}
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs

@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data);
}
}

24
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
/// <inheritdoc/>
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)

24
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
/// <inheritdoc/>
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)

28
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs

@ -183,19 +183,21 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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)

28
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs

@ -183,19 +183,21 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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)

17
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs

@ -106,16 +106,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs

@ -66,12 +66,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Texts?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Texts);
}
}

13
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs

@ -90,14 +90,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
}
}

18
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
/// <inheritdoc/>
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);
}
}
}

10
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));
}
/// <summary>
@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Curve?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Curve);
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs

@ -67,12 +67,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Descriptions?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Descriptions);
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs

@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data);
}
}

11
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs

@ -83,13 +83,10 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
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);
}
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs

@ -77,13 +77,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs

@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.SignatureData?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.SignatureData);
}
}

17
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs

@ -166,16 +166,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
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);
}
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs

@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Text?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Text);
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs

@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data);
}
}

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs

@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data);
}
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs

@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data);
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs

@ -65,12 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data);
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs

@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data);
}
}

13
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs

@ -86,14 +86,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs

@ -64,12 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (base.GetHashCode() * 397) ^ (this.Data?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Signature, this.Data);
}
}

13
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs

@ -86,14 +86,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
}
}

15
src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs

@ -142,15 +142,12 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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)

13
src/ImageSharp/MetaData/Profiles/ICC/Various/IccColorantTableEntry.cs

@ -102,14 +102,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
/// <inheritdoc/>

26
src/ImageSharp/MetaData/Profiles/ICC/Various/IccNamedColor.cs

@ -80,27 +80,23 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc/>
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);
}
/// <inheritdoc/>
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);
}
/// <inheritdoc/>
public override string ToString()
{
return this.Name;
}
public override string ToString() => this.Name;
}
}

10
src/ImageSharp/MetaData/Profiles/ICC/Various/IccPositionNumber.cs

@ -73,15 +73,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
this.Size == other.Size;
/// <inheritdoc/>
public override int GetHashCode()
{
return unchecked((int)(this.Offset ^ this.Size));
}
public override int GetHashCode() => unchecked((int)(this.Offset ^ this.Size));
/// <inheritdoc/>
public override string ToString()
{
return $"{this.Offset}; {this.Size}";
}
public override string ToString() => $"{this.Offset}; {this.Size}";
}
}

24
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));
}
/// <summary>
@ -87,16 +84,13 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
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);
}
}
}

13
src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileId.cs

@ -101,14 +101,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
/// <inheritdoc/>

12
src/ImageSharp/MetaData/Profiles/ICC/Various/IccProfileSequenceIdentifier.cs

@ -18,10 +18,8 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <param name="description">Description of the profile</param>
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));
}
/// <summary>
@ -46,12 +44,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
}
/// <inheritdoc />
public override int GetHashCode()
{
unchecked
{
return (this.Id.GetHashCode() * 397) ^ (this.Description?.GetHashCode() ?? 0);
}
}
public override int GetHashCode() => HashCode.Combine(this.Id, this.Description);
}
}

15
src/ImageSharp/MetaData/Profiles/ICC/Various/IccResponseNumber.cs

@ -73,20 +73,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
this.MeasurementValue == other.MeasurementValue;
/// <inheritdoc/>
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);
/// <inheritdoc/>
public override string ToString()
{
return $"Code: {this.DeviceCode}; Value: {this.MeasurementValue}";
}
public override string ToString() => $"Code: {this.DeviceCode}; Value: {this.MeasurementValue}";
}
}

8
src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs

@ -85,13 +85,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
}
/// <inheritdoc/>

14
src/ImageSharp/MetaData/Profiles/ICC/Various/IccTagTableEntry.cs

@ -76,20 +76,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
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);
/// <inheritdoc/>
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);
}
/// <inheritdoc/>

7
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
/// <inheritdoc/>
[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);
}
}

7
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
/// <inheritdoc/>
[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);
/// <inheritdoc/>
public override string ToString() => $"Rgb24({this.R}, {this.G}, {this.B})";

7
src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs

@ -189,11 +189,6 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc />
[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);
}
}

7
src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs

@ -197,11 +197,6 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
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);
}
}

33
src/ImageSharp/Primitives/DenseMatrix{T}.cs

@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.Primitives
/// <returns>The <see typeparam="T"/> at the specified position.</returns>
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
/// <returns>
/// The <see cref="DenseMatrix{T}"/> representation on the source data.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public static implicit operator DenseMatrix<T>(T[,] data) => new DenseMatrix<T>(data);
/// <summary>
@ -135,9 +135,9 @@ namespace SixLabors.ImageSharp.Primitives
/// <returns>
/// The <see cref="T:T[,]"/> representation on the source data.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
#pragma warning disable SA1008 // Opening parenthesis should be spaced correctly
public static implicit operator T[,] (DenseMatrix<T> data)
public static implicit operator T[,] (in DenseMatrix<T> 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;
}
/// <summary>
/// Transposes the rows and columns of the dense matrix.
/// </summary>
/// <returns>The <see cref="DenseMatrix{T}"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public DenseMatrix<T> Transpose()
{
var result = new DenseMatrix<T>(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;
}
/// <summary>
/// Fills the matrix with the given value
/// </summary>
/// <param name="value">The value to fill each item with</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void Fill(T value) => this.Span.Fill(value);
/// <summary>
/// Clears the matrix setting each value to the default value for the element type
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void Clear() => this.Span.Clear();
/// <summary>

7
src/ImageSharp/Primitives/ValueSize.cs

@ -133,9 +133,6 @@ namespace SixLabors.ImageSharp.Primitives
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashHelpers.Combine(this.Value.GetHashCode(), this.Type.GetHashCode());
}
public override int GetHashCode() => HashCode.Combine(this.Value, this.Type);
}
}
}

18
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();
}
/// <summary>
@ -49,24 +49,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public DenseMatrix<float> KernelY { get; }
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
}
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) => new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
/// <summary>
/// Create a 1 dimensional Box kernel.
/// </summary>
/// <param name="horizontal">Whether to calculate a horizontal kernel.</param>
/// <returns>The <see cref="DenseMatrix{T}"/></returns>
private DenseMatrix<float> CreateBoxKernel(bool horizontal)
private DenseMatrix<float> CreateBoxKernel()
{
int size = this.kernelSize;
DenseMatrix<float> kernel = horizontal
? new DenseMatrix<float>(size, 1)
: new DenseMatrix<float>(1, size);
var kernel = new DenseMatrix<float>(size, 1);
kernel.Fill(1.0F / size);
kernel.Fill(1F / size);
return kernel;
}

51
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
/// </summary>
/// <param name="sigma">The 'sigma' value representing the weight of the blur.</param>
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/
}
/// <summary>
@ -40,11 +38,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// The 'radius' value representing the size of the area to sample.
/// </param>
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);
}
/// <summary>
@ -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();
}
/// <summary>
@ -82,22 +77,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
}
=> new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
/// <summary>
/// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function
/// </summary>
/// <param name="horizontal">Whether to calculate a horizontal kernel.</param>
/// <returns>The <see cref="DenseMatrix{T}"/></returns>
private DenseMatrix<float> CreateGaussianKernel(bool horizontal)
private DenseMatrix<float> CreateGaussianKernel()
{
int size = this.kernelSize;
float weight = this.Sigma;
DenseMatrix<float> kernel = horizontal
? new DenseMatrix<float>(size, 1)
: new DenseMatrix<float>(1, size);
var kernel = new DenseMatrix<float>(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;

86
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.
/// </param>
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/
}
/// <summary>
@ -41,11 +40,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// The 'radius' value representing the size of the area to sample.
/// </param>
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);
}
/// <summary>
@ -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();
}
/// <summary>
@ -83,91 +79,49 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
}
=> new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
/// <summary>
/// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function
/// </summary>
/// <param name="horizontal">Whether to calculate a horizontal kernel.</param>
/// <returns>The <see cref="DenseMatrix{T}"/></returns>
private DenseMatrix<float> CreateGaussianKernel(bool horizontal)
private DenseMatrix<float> CreateGaussianKernel()
{
int size = this.kernelSize;
float weight = this.Sigma;
DenseMatrix<float> kernel = horizontal
? new DenseMatrix<float>(size, 1)
: new DenseMatrix<float>(1, size);
var kernel = new DenseMatrix<float>(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;

2
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<TPixel>.Instance.ToScaledVector4(configuration, this.Palette, this.paletteVector);

3
src/ImageSharp/Processing/Processors/Dithering/PixelPair.cs

@ -43,7 +43,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
=> obj is PixelPair<TPixel> other && this.First.Equals(other.First) && this.Second.Equals(other.Second);
/// <inheritdoc/>
public override int GetHashCode()
=> HashHelpers.Combine(this.First.GetHashCode(), this.Second.GetHashCode());
public override int GetHashCode() => HashCode.Combine(this.First, this.Second);
}
}

13
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);
}

79
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
/// </summary>
internal static class TransformUtils
{
/// <summary>
/// Applies the projective transform against the given coordinates flattened into the 2D space.
/// </summary>
/// <param name="x">The "x" vector coordinate.</param>
/// <param name="y">The "y" vector coordinate.</param>
/// <param name="matrix">The transform matrix.</param>
/// <returns>The <see cref="Vector2"/>.</returns>
[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);
}
/// <summary>
/// Creates a centered rotation matrix using the given rotation in degrees and the source size.
/// </summary>
@ -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);
}

26
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")]

1
tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs

@ -1,5 +1,4 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Jobs;
namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath
{

1
tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs

@ -1,5 +1,4 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Jobs;
namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath
{

1
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;

2
tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj

@ -16,7 +16,7 @@
<Compile Include="..\ImageSharp.Tests\TestUtilities\TestEnvironment.cs" Link="Tests\TestEnvironment.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.10.14" />
<PackageReference Include="BenchmarkDotNet" Version="0.11.3" />
<PackageReference Include="Colourful" Version="2.0.0" />
<PackageReference Include="SixLabors.Shapes.Text" Version="1.0.0-beta0007" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0" />

8
tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj

@ -18,19 +18,13 @@
<ProjectReference Include="..\..\src\ImageSharp\ImageSharp.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BitMiracle.LibJpeg.NET" Version="1.4.280" />
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.9.0.1" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="Moq" Version="4.8.3" />
<!--<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />-->
<!--<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />-->
<PackageReference Include="Moq" Version="4.10.0" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\ImageSharp.Tests\**\*.cs" Exclude="bin\**;obj\**" Link="Tests\%(RecursiveDir)%(Filename)%(Extension)" />
<Compile Remove="..\ImageSharp.Tests\obj\**\*.cs" />
<Compile Remove="..\ImageSharp.Tests\bin\**\*.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
</Project>

43
tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

@ -55,6 +55,30 @@ namespace SixLabors.ImageSharp.Tests
}
}
[Theory]
[WithFile(WinBmpv2, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecodeBmpv2<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new BmpDecoder()))
{
image.DebugSave(provider, "png");
image.CompareToOriginal(provider);
}
}
[Theory]
[WithFile(Bit8Palette4, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode4BytePerEntryPalette<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> 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<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
var testFile = TestFile.Create(imagePath);
using (var stream = new MemoryStream(testFile.Bytes, false))
using (Image<TPixel> 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);
}
}
}

7
tests/ImageSharp.Tests/ImageSharp.Tests.csproj

@ -28,15 +28,12 @@
<ItemGroup>
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="7.9.0.1" />
<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.console" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<PackageReference Include="Moq" Version="4.8.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="Moq" Version="4.10.0" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\stylecop.json" />

24
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<float>(FloydSteinbergMatrix);
Assert.Equal(FloydSteinbergMatrix, actual);
}
[Fact]
public void DenseMatrixCanTranspose()
{
var dense = new DenseMatrix<int>(3, 1);
dense[0, 0] = 1;
dense[0, 1] = 2;
dense[0, 2] = 3;
DenseMatrix<int> 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]);
}
}
}

5
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs

@ -208,10 +208,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
var result = new TheoryData<string, int, int>();
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 =
{

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save