Browse Source

Merge pull request #1087 from SixLabors/af/merge-core-2

Merge SixLabors.Core sources into ImageSharp
pull/1093/head
James Jackson-South 6 years ago
committed by GitHub
parent
commit
4973f5f160
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      Directory.Build.targets
  2. 1
      GitVersion.yml
  3. 6
      ci-test.ps1
  4. 2
      src/Directory.Build.targets
  5. 1
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  6. 2
      src/ImageSharp/Advanced/ParallelUtils/ParallelExecutionSettings.cs
  7. 2
      src/ImageSharp/Advanced/ParallelUtils/ParallelHelper.cs
  8. 1
      src/ImageSharp/Common/Extensions/StreamExtensions.cs
  9. 1
      src/ImageSharp/Common/Helpers/Buffer2DUtils.cs
  10. 1
      src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
  11. 1
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  12. 1
      src/ImageSharp/Common/Helpers/Vector4Utils.cs
  13. 2
      src/ImageSharp/Configuration.cs
  14. 1
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  15. 1
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  16. 2
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  17. 1
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  18. 1
      src/ImageSharp/Formats/Gif/LzwDecoder.cs
  19. 1
      src/ImageSharp/Formats/Gif/LzwEncoder.cs
  20. 1
      src/ImageSharp/Formats/Jpeg/Components/Decoder/IJpegComponent.cs
  21. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs
  22. 1
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs
  23. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
  24. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs
  25. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
  26. 2
      src/ImageSharp/Formats/Jpeg/Components/SizeExtensions.cs
  27. 3
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  28. 2
      src/ImageSharp/Formats/Png/PngChunk.cs
  29. 1
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  30. 1
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  31. 1
      src/ImageSharp/Formats/Png/PngThrowHelper.cs
  32. 2
      src/ImageSharp/Formats/Png/Zlib/Deflater.cs
  33. 2
      src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs
  34. 2
      src/ImageSharp/Formats/Png/Zlib/DeflaterHuffman.cs
  35. 2
      src/ImageSharp/Formats/Png/Zlib/DeflaterOutputStream.cs
  36. 2
      src/ImageSharp/Formats/Png/Zlib/DeflaterPendingBuffer.cs
  37. 2
      src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs
  38. 1
      src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
  39. 2
      src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
  40. 34
      src/ImageSharp/GeometryUtilities.cs
  41. 2
      src/ImageSharp/IO/DoubleBufferedStreamReader.cs
  42. 1
      src/ImageSharp/Image.Decode.cs
  43. 1
      src/ImageSharp/Image.cs
  44. 4
      src/ImageSharp/ImageFrame.cs
  45. 2
      src/ImageSharp/ImageFrame{TPixel}.cs
  46. 2
      src/ImageSharp/ImageInfoExtensions.cs
  47. 29
      src/ImageSharp/ImageSharp.csproj
  48. 1
      src/ImageSharp/Image{TPixel}.cs
  49. 21
      src/ImageSharp/Memory/Allocators/AllocationOptions.cs
  50. 85
      src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.Buffer{T}.cs
  51. 72
      src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.CommonFactoryMethods.cs
  52. 150
      src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.cs
  53. 18
      src/ImageSharp/Memory/Allocators/IManagedByteBuffer.cs
  54. 60
      src/ImageSharp/Memory/Allocators/Internals/BasicArrayBuffer.cs
  55. 20
      src/ImageSharp/Memory/Allocators/Internals/BasicByteBuffer.cs
  56. 45
      src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs
  57. 39
      src/ImageSharp/Memory/Allocators/MemoryAllocator.cs
  58. 30
      src/ImageSharp/Memory/Allocators/SimpleGcMemoryAllocator.cs
  59. 2
      src/ImageSharp/Memory/Buffer2DExtensions.cs
  60. 4
      src/ImageSharp/Memory/Buffer2D{T}.cs
  61. 2
      src/ImageSharp/Memory/BufferArea{T}.cs
  62. 3
      src/ImageSharp/Memory/MemoryAllocatorExtensions.cs
  63. 2
      src/ImageSharp/Memory/MemorySource.cs
  64. 5
      src/ImageSharp/Memory/RowInterval.cs
  65. 1
      src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs
  66. 1
      src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs
  67. 1
      src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs
  68. 2
      src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.Number.cs
  69. 2
      src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.NumberArray.cs
  70. 2
      src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.Rational.cs
  71. 2
      src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.RationalArray.cs
  72. 2
      src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.SignedRational.cs
  73. 2
      src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.SignedRationalArray.cs
  74. 1
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumber.cs
  75. 2
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumberArray.cs
  76. 1
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRational.cs
  77. 1
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRationalArray.cs
  78. 1
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedRational.cs
  79. 2
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedRationalArray.cs
  80. 1
      src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs
  81. 2
      src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs
  82. 112
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
  83. 4
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt
  84. 2
      src/ImageSharp/Primitives/ColorMatrix.cs
  85. 2
      src/ImageSharp/Primitives/Complex64.cs
  86. 2
      src/ImageSharp/Primitives/ComplexVector4.cs
  87. 3
      src/ImageSharp/Primitives/DenseMatrix{T}.cs
  88. 2
      src/ImageSharp/Primitives/LongRational.cs
  89. 101
      src/ImageSharp/Primitives/Matrix3x2Extensions.cs
  90. 2
      src/ImageSharp/Primitives/Number.cs
  91. 288
      src/ImageSharp/Primitives/Point.cs
  92. 293
      src/ImageSharp/Primitives/PointF.cs
  93. 2
      src/ImageSharp/Primitives/Rational.cs
  94. 463
      src/ImageSharp/Primitives/Rectangle.cs
  95. 396
      src/ImageSharp/Primitives/RectangleF.cs
  96. 2
      src/ImageSharp/Primitives/SignedRational.cs
  97. 296
      src/ImageSharp/Primitives/Size.cs
  98. 233
      src/ImageSharp/Primitives/SizeF.cs
  99. 3
      src/ImageSharp/Primitives/ValueSize.cs
  100. 1
      src/ImageSharp/Processing/AffineTransformBuilder.cs

6
Directory.Build.targets

@ -23,10 +23,12 @@
<PackageReference Update="StyleCop.Analyzers" PrivateAssets="All" Version="1.1.118" />
<!--Src Dependencies-->
<PackageReference Update="SixLabors.Core" Version="1.0.0-beta0008" />
<PackageReference Update="System.Buffers" Version="4.5.0" />
<PackageReference Update="System.IO.Compression" Version="4.3.0" />
<PackageReference Update="System.IO.UnmanagedMemoryStream" Version="4.3.0" />
<PackageReference Update="System.Runtime.CompilerServices.Unsafe" Version="4.5.1" />
<PackageReference Update="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Update="System.Memory" Version="4.5.3" />
<PackageReference Update="System.Runtime.CompilerServices.Unsafe" Version="4.7" />
<PackageReference Update="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Update="System.ValueTuple" Version="4.5.0" />

1
GitVersion.yml

@ -2,5 +2,6 @@ continuous-delivery-fallback-tag: ci
branches:
master:
tag: unstable
mode: ContinuousDeployment
pull-request:
tag: pr

6
ci-test.ps1

@ -34,8 +34,4 @@ elseif ($platform -eq '-x86' -and $targetFramework -match $netFxRegex) {
else {
dotnet test --no-build -c Release -f $targetFramework
}
# Explicitly exit with 0 to ignore errors caused by coverlet attempting to read
# project files that dotnet test is set to ignore.
exit 0
}

2
src/Directory.Build.targets

@ -50,6 +50,6 @@
<!-- Empty target so that `dotnet test` will work on the solution -->
<!-- https://github.com/Microsoft/vstest/issues/411 -->
<Target Name="VSTest" />
<Target Name="VSTest" Condition="'$(IsTestProject)' == 'true'"/>
</Project>

1
src/ImageSharp/Advanced/AdvancedImageExtensions.cs

@ -6,7 +6,6 @@ using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Advanced
{

2
src/ImageSharp/Advanced/ParallelUtils/ParallelExecutionSettings.cs

@ -4,7 +4,7 @@
using System;
using System.Threading.Tasks;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Advanced.ParallelUtils
{

2
src/ImageSharp/Advanced/ParallelUtils/ParallelHelper.cs

@ -7,8 +7,6 @@ using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Advanced.ParallelUtils
{

1
src/ImageSharp/Common/Extensions/StreamExtensions.cs

@ -5,7 +5,6 @@ using System;
using System.Buffers;
using System.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp
{

1
src/ImageSharp/Common/Helpers/Buffer2DUtils.cs

@ -8,7 +8,6 @@ using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp
{

1
src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs

@ -6,7 +6,6 @@ using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp
{

1
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -6,7 +6,6 @@ using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp
{

1
src/ImageSharp/Common/Helpers/Vector4Utils.cs

@ -5,7 +5,6 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp
{

2
src/ImageSharp/Configuration.cs

@ -10,8 +10,8 @@ using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Processing;
using SixLabors.Memory;
namespace SixLabors.ImageSharp
{

1
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -11,7 +11,6 @@ using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Bmp
{

1
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -12,7 +12,6 @@ using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Bmp
{

2
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -10,8 +10,6 @@ using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Gif
{

1
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -12,7 +12,6 @@ using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Gif
{

1
src/ImageSharp/Formats/Gif/LzwDecoder.cs

@ -8,7 +8,6 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Gif
{

1
src/ImageSharp/Formats/Gif/LzwEncoder.cs

@ -8,7 +8,6 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Gif
{

1
src/ImageSharp/Formats/Jpeg/Components/Decoder/IJpegComponent.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/IRawJpegData.cs

@ -3,8 +3,6 @@
using System;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
/// <inheritdoc />

1
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs

@ -4,7 +4,6 @@
using System;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs

@ -4,8 +4,6 @@
using System;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs

@ -6,8 +6,6 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs

@ -7,8 +7,6 @@ using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
using JpegColorConverter = SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters.JpegColorConverter;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder

2
src/ImageSharp/Formats/Jpeg/Components/SizeExtensions.cs

@ -4,8 +4,6 @@
using System;
using System.Numerics;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components
{
/// <summary>

3
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -15,9 +15,6 @@ using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.Metadata.Profiles.Icc;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg
{

2
src/ImageSharp/Formats/Png/PngChunk.cs

@ -1,7 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Png
{

1
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -17,7 +17,6 @@ using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Png
{

1
src/ImageSharp/Formats/Png/PngEncoderCore.cs

@ -17,7 +17,6 @@ using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Png
{

1
src/ImageSharp/Formats/Png/PngThrowHelper.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Png

2
src/ImageSharp/Formats/Png/Zlib/Deflater.cs

@ -3,7 +3,7 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{

2
src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs

@ -4,7 +4,7 @@
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{

2
src/ImageSharp/Formats/Png/Zlib/DeflaterHuffman.cs

@ -5,7 +5,7 @@ using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{

2
src/ImageSharp/Formats/Png/Zlib/DeflaterOutputStream.cs

@ -3,7 +3,7 @@
using System;
using System.IO;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{

2
src/ImageSharp/Formats/Png/Zlib/DeflaterPendingBuffer.cs

@ -4,7 +4,7 @@
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{

2
src/ImageSharp/Formats/Png/Zlib/ZlibDeflateStream.cs

@ -3,7 +3,7 @@
using System;
using System.IO;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Png.Zlib
{

1
src/ImageSharp/Formats/Tga/TgaDecoderCore.cs

@ -9,7 +9,6 @@ using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Tga
{

2
src/ImageSharp/Formats/Tga/TgaEncoderCore.cs

@ -4,14 +4,12 @@
using System;
using System.Buffers.Binary;
using System.IO;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Tga
{

34
src/ImageSharp/GeometryUtilities.cs

@ -0,0 +1,34 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors
{
/// <summary>
/// Utility class for common geometric functions.
/// </summary>
public static class GeometryUtilities
{
/// <summary>
/// Converts a degree (360-periodic) angle to a radian (2*Pi-periodic) angle.
/// </summary>
/// <param name="degree">The angle in degrees.</param>
/// <returns>
/// The <see cref="float"/> representing the degree as radians.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DegreeToRadian(float degree) => degree * (MathF.PI / 180F);
/// <summary>
/// Converts a radian (2*Pi-periodic) angle to a degree (360-periodic) angle.
/// </summary>
/// <param name="radian">The angle in radians.</param>
/// <returns>
/// The <see cref="float"/> representing the degree as radians.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float RadianToDegree(float radian) => radian / (MathF.PI / 180F);
}
}

2
src/ImageSharp/IO/DoubleBufferedStreamReader.cs

@ -6,7 +6,7 @@ using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.IO
{

1
src/ImageSharp/Image.Decode.cs

@ -8,7 +8,6 @@ using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
namespace SixLabors.ImageSharp
{

1
src/ImageSharp/Image.cs

@ -8,7 +8,6 @@ using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp
{

4
src/ImageSharp/ImageFrame.cs

@ -2,11 +2,9 @@
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp
{

2
src/ImageSharp/ImageFrame{TPixel}.cs

@ -10,8 +10,6 @@ using SixLabors.ImageSharp.Advanced.ParallelUtils;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp
{

2
src/ImageSharp/ImageInfoExtensions.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.Primitives;
namespace SixLabors.ImageSharp
{
/// <summary>

29
src/ImageSharp/ImageSharp.csproj

@ -19,6 +19,23 @@
<RootNamespace>SixLabors.ImageSharp</RootNamespace>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) OR '$(TargetFramework)' == 'net472'">
<PackageReference Include="System.Numerics.Vectors"/>
<PackageReference Include="System.Buffers"/>
<PackageReference Include="System.Memory"/>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="System.IO.Compression" />
<PackageReference Include="System.IO.UnmanagedMemoryStream" />
<PackageReference Include="System.Threading.Tasks.Parallel" />
<PackageReference Include="System.ValueTuple" />
</ItemGroup>
<ItemGroup>
<Compile Update="Formats\Jpeg\Components\Block8x8F.Generated.cs">
<DesignTime>True</DesignTime>
@ -187,18 +204,6 @@
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="SixLabors.Core" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="System.IO.Compression" />
<PackageReference Include="System.IO.UnmanagedMemoryStream" />
<PackageReference Include="System.Threading.Tasks.Parallel" />
<PackageReference Include="System.ValueTuple" />
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>

1
src/ImageSharp/Image{TPixel}.cs

@ -9,7 +9,6 @@ using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp
{

21
src/ImageSharp/Memory/Allocators/AllocationOptions.cs

@ -0,0 +1,21 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Options for allocating buffers.
/// </summary>
public enum AllocationOptions
{
/// <summary>
/// Indicates that the buffer should just be allocated.
/// </summary>
None,
/// <summary>
/// Indicates that the allocated buffer should be cleaned following allocation.
/// </summary>
Clean
}
}

85
src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.Buffer{T}.cs

@ -0,0 +1,85 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory.Internals;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Contains <see cref="Buffer{T}"/> and <see cref="ManagedByteBuffer"/>.
/// </summary>
public partial class ArrayPoolMemoryAllocator
{
/// <summary>
/// The buffer implementation of <see cref="ArrayPoolMemoryAllocator"/>.
/// </summary>
private class Buffer<T> : ManagedBufferBase<T>
where T : struct
{
/// <summary>
/// The length of the buffer.
/// </summary>
private readonly int length;
/// <summary>
/// A weak reference to the source pool.
/// </summary>
/// <remarks>
/// By using a weak reference here, we are making sure that array pools and their retained arrays are always GC-ed
/// after a call to <see cref="ArrayPoolMemoryAllocator.ReleaseRetainedResources"/>, regardless of having buffer instances still being in use.
/// </remarks>
private WeakReference<ArrayPool<byte>> sourcePoolReference;
public Buffer(byte[] data, int length, ArrayPool<byte> sourcePool)
{
this.Data = data;
this.length = length;
this.sourcePoolReference = new WeakReference<ArrayPool<byte>>(sourcePool);
}
/// <summary>
/// Gets the buffer as a byte array.
/// </summary>
protected byte[] Data { get; private set; }
/// <inheritdoc />
public override Span<T> GetSpan() => MemoryMarshal.Cast<byte, T>(this.Data.AsSpan()).Slice(0, this.length);
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
if (!disposing || this.Data is null || this.sourcePoolReference is null)
{
return;
}
if (this.sourcePoolReference.TryGetTarget(out ArrayPool<byte> pool))
{
pool.Return(this.Data);
}
this.sourcePoolReference = null;
this.Data = null;
}
protected override object GetPinnableObject() => this.Data;
}
/// <summary>
/// The <see cref="IManagedByteBuffer"/> implementation of <see cref="ArrayPoolMemoryAllocator"/>.
/// </summary>
private sealed class ManagedByteBuffer : Buffer<byte>, IManagedByteBuffer
{
public ManagedByteBuffer(byte[] data, int length, ArrayPool<byte> sourcePool)
: base(data, length, sourcePool)
{
}
/// <inheritdoc />
public byte[] Array => this.Data;
}
}
}

72
src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.CommonFactoryMethods.cs

@ -0,0 +1,72 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Contains common factory methods and configuration constants.
/// </summary>
public partial class ArrayPoolMemoryAllocator
{
/// <summary>
/// The default value for: maximum size of pooled arrays in bytes.
/// Currently set to 24MB, which is equivalent to 8 megapixels of raw RGBA32 data.
/// </summary>
internal const int DefaultMaxPooledBufferSizeInBytes = 24 * 1024 * 1024;
/// <summary>
/// The value for: The threshold to pool arrays in <see cref="largeArrayPool"/> which has less buckets for memory safety.
/// </summary>
private const int DefaultBufferSelectorThresholdInBytes = 8 * 1024 * 1024;
/// <summary>
/// The default bucket count for <see cref="largeArrayPool"/>.
/// </summary>
private const int DefaultLargePoolBucketCount = 6;
/// <summary>
/// The default bucket count for <see cref="normalArrayPool"/>.
/// </summary>
private const int DefaultNormalPoolBucketCount = 16;
/// <summary>
/// This is the default. Should be good for most use cases.
/// </summary>
/// <returns>The memory manager.</returns>
public static ArrayPoolMemoryAllocator CreateDefault()
{
return new ArrayPoolMemoryAllocator(
DefaultMaxPooledBufferSizeInBytes,
DefaultBufferSelectorThresholdInBytes,
DefaultLargePoolBucketCount,
DefaultNormalPoolBucketCount);
}
/// <summary>
/// For environments with very limited memory capabilities, only small buffers like image rows are pooled.
/// </summary>
/// <returns>The memory manager.</returns>
public static ArrayPoolMemoryAllocator CreateWithMinimalPooling()
{
return new ArrayPoolMemoryAllocator(64 * 1024, 32 * 1024, 8, 24);
}
/// <summary>
/// For environments with limited memory capabilities, only small array requests are pooled, which can result in reduced throughput.
/// </summary>
/// <returns>The memory manager.</returns>
public static ArrayPoolMemoryAllocator CreateWithModeratePooling()
{
return new ArrayPoolMemoryAllocator(1024 * 1024, 32 * 1024, 16, 24);
}
/// <summary>
/// For environments where memory capabilities are not an issue, the maximum amount of array requests are pooled which results in optimal throughput.
/// </summary>
/// <returns>The memory manager.</returns>
public static ArrayPoolMemoryAllocator CreateWithAggressivePooling()
{
return new ArrayPoolMemoryAllocator(128 * 1024 * 1024, 32 * 1024 * 1024, 16, 32);
}
}
}

150
src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.cs

@ -0,0 +1,150 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Implements <see cref="MemoryAllocator"/> by allocating memory from <see cref="ArrayPool{T}"/>.
/// </summary>
public sealed partial class ArrayPoolMemoryAllocator : MemoryAllocator
{
private readonly int maxArraysPerBucketNormalPool;
private readonly int maxArraysPerBucketLargePool;
/// <summary>
/// The <see cref="ArrayPool{T}"/> for small-to-medium buffers which is not kept clean.
/// </summary>
private ArrayPool<byte> normalArrayPool;
/// <summary>
/// The <see cref="ArrayPool{T}"/> for huge buffers, which is not kept clean.
/// </summary>
private ArrayPool<byte> largeArrayPool;
/// <summary>
/// Initializes a new instance of the <see cref="ArrayPoolMemoryAllocator"/> class.
/// </summary>
public ArrayPoolMemoryAllocator()
: this(DefaultMaxPooledBufferSizeInBytes, DefaultBufferSelectorThresholdInBytes)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ArrayPoolMemoryAllocator"/> class.
/// </summary>
/// <param name="maxPoolSizeInBytes">The maximum size of pooled arrays. Arrays over the thershold are gonna be always allocated.</param>
public ArrayPoolMemoryAllocator(int maxPoolSizeInBytes)
: this(maxPoolSizeInBytes, GetLargeBufferThresholdInBytes(maxPoolSizeInBytes))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ArrayPoolMemoryAllocator"/> class.
/// </summary>
/// <param name="maxPoolSizeInBytes">The maximum size of pooled arrays. Arrays over the thershold are gonna be always allocated.</param>
/// <param name="poolSelectorThresholdInBytes">Arrays over this threshold will be pooled in <see cref="largeArrayPool"/> which has less buckets for memory safety.</param>
public ArrayPoolMemoryAllocator(int maxPoolSizeInBytes, int poolSelectorThresholdInBytes)
: this(maxPoolSizeInBytes, poolSelectorThresholdInBytes, DefaultLargePoolBucketCount, DefaultNormalPoolBucketCount)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ArrayPoolMemoryAllocator"/> class.
/// </summary>
/// <param name="maxPoolSizeInBytes">The maximum size of pooled arrays. Arrays over the thershold are gonna be always allocated.</param>
/// <param name="poolSelectorThresholdInBytes">The threshold to pool arrays in <see cref="largeArrayPool"/> which has less buckets for memory safety.</param>
/// <param name="maxArraysPerBucketLargePool">Max arrays per bucket for the large array pool.</param>
/// <param name="maxArraysPerBucketNormalPool">Max arrays per bucket for the normal array pool.</param>
public ArrayPoolMemoryAllocator(int maxPoolSizeInBytes, int poolSelectorThresholdInBytes, int maxArraysPerBucketLargePool, int maxArraysPerBucketNormalPool)
{
Guard.MustBeGreaterThan(maxPoolSizeInBytes, 0, nameof(maxPoolSizeInBytes));
Guard.MustBeLessThanOrEqualTo(poolSelectorThresholdInBytes, maxPoolSizeInBytes, nameof(poolSelectorThresholdInBytes));
this.MaxPoolSizeInBytes = maxPoolSizeInBytes;
this.PoolSelectorThresholdInBytes = poolSelectorThresholdInBytes;
this.maxArraysPerBucketLargePool = maxArraysPerBucketLargePool;
this.maxArraysPerBucketNormalPool = maxArraysPerBucketNormalPool;
this.InitArrayPools();
}
/// <summary>
/// Gets the maximum size of pooled arrays in bytes.
/// </summary>
public int MaxPoolSizeInBytes { get; }
/// <summary>
/// Gets the threshold to pool arrays in <see cref="largeArrayPool"/> which has less buckets for memory safety.
/// </summary>
public int PoolSelectorThresholdInBytes { get; }
/// <inheritdoc />
public override void ReleaseRetainedResources()
{
this.InitArrayPools();
}
/// <inheritdoc />
public override IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
{
Guard.MustBeGreaterThanOrEqualTo(length, 0, nameof(length));
int itemSizeBytes = Unsafe.SizeOf<T>();
int bufferSizeInBytes = length * itemSizeBytes;
if (bufferSizeInBytes < 0)
{
throw new ArgumentOutOfRangeException(
nameof(length),
$"{nameof(ArrayPoolMemoryAllocator)} can not allocate {length} elements of {typeof(T).Name}.");
}
ArrayPool<byte> pool = this.GetArrayPool(bufferSizeInBytes);
byte[] byteArray = pool.Rent(bufferSizeInBytes);
var buffer = new Buffer<T>(byteArray, length, pool);
if (options == AllocationOptions.Clean)
{
buffer.GetSpan().Clear();
}
return buffer;
}
/// <inheritdoc />
public override IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options = AllocationOptions.None)
{
Guard.MustBeGreaterThanOrEqualTo(length, 0, nameof(length));
ArrayPool<byte> pool = this.GetArrayPool(length);
byte[] byteArray = pool.Rent(length);
var buffer = new ManagedByteBuffer(byteArray, length, pool);
if (options == AllocationOptions.Clean)
{
buffer.GetSpan().Clear();
}
return buffer;
}
private static int GetLargeBufferThresholdInBytes(int maxPoolSizeInBytes)
{
return maxPoolSizeInBytes / 4;
}
private ArrayPool<byte> GetArrayPool(int bufferSizeInBytes)
{
return bufferSizeInBytes <= this.PoolSelectorThresholdInBytes ? this.normalArrayPool : this.largeArrayPool;
}
private void InitArrayPools()
{
this.largeArrayPool = ArrayPool<byte>.Create(this.MaxPoolSizeInBytes, this.maxArraysPerBucketLargePool);
this.normalArrayPool = ArrayPool<byte>.Create(this.PoolSelectorThresholdInBytes, this.maxArraysPerBucketNormalPool);
}
}
}

18
src/ImageSharp/Memory/Allocators/IManagedByteBuffer.cs

@ -0,0 +1,18 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Represents a byte buffer backed by a managed array. Useful for interop with classic .NET API-s.
/// </summary>
public interface IManagedByteBuffer : IMemoryOwner<byte>
{
/// <summary>
/// Gets the managed array backing this buffer instance.
/// </summary>
byte[] Array { get; }
}
}

60
src/ImageSharp/Memory/Allocators/Internals/BasicArrayBuffer.cs

@ -0,0 +1,60 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.Memory.Internals
{
/// <summary>
/// Wraps an array as an <see cref="IManagedByteBuffer"/> instance.
/// </summary>
/// <inheritdoc />
internal class BasicArrayBuffer<T> : ManagedBufferBase<T>
where T : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="BasicArrayBuffer{T}"/> class.
/// </summary>
/// <param name="array">The array.</param>
/// <param name="length">The length of the buffer.</param>
public BasicArrayBuffer(T[] array, int length)
{
DebugGuard.MustBeLessThanOrEqualTo(length, array.Length, nameof(length));
this.Array = array;
this.Length = length;
}
/// <summary>
/// Initializes a new instance of the <see cref="BasicArrayBuffer{T}"/> class.
/// </summary>
/// <param name="array">The array.</param>
public BasicArrayBuffer(T[] array)
: this(array, array.Length)
{
}
/// <summary>
/// Gets the array.
/// </summary>
public T[] Array { get; }
/// <summary>
/// Gets the length.
/// </summary>
public int Length { get; }
/// <inheritdoc />
public override Span<T> GetSpan() => this.Array.AsSpan(0, this.Length);
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
}
/// <inheritdoc />
protected override object GetPinnableObject()
{
return this.Array;
}
}
}

20
src/ImageSharp/Memory/Allocators/Internals/BasicByteBuffer.cs

@ -0,0 +1,20 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Memory.Internals
{
/// <summary>
/// Provides an <see cref="IManagedByteBuffer"/> based on <see cref="BasicArrayBuffer{T}"/>.
/// </summary>
internal sealed class BasicByteBuffer : BasicArrayBuffer<byte>, IManagedByteBuffer
{
/// <summary>
/// Initializes a new instance of the <see cref="BasicByteBuffer"/> class.
/// </summary>
/// <param name="array">The byte array.</param>
internal BasicByteBuffer(byte[] array)
: base(array)
{
}
}
}

45
src/ImageSharp/Memory/Allocators/Internals/ManagedBufferBase.cs

@ -0,0 +1,45 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Memory.Internals
{
/// <summary>
/// Provides a base class for <see cref="IMemoryOwner{T}"/> implementations by implementing pinning logic for <see cref="MemoryManager{T}"/> adaption.
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
internal abstract class ManagedBufferBase<T> : MemoryManager<T>
where T : struct
{
private GCHandle pinHandle;
/// <inheritdoc />
public override unsafe MemoryHandle Pin(int elementIndex = 0)
{
if (!this.pinHandle.IsAllocated)
{
this.pinHandle = GCHandle.Alloc(this.GetPinnableObject(), GCHandleType.Pinned);
}
void* ptr = (void*)this.pinHandle.AddrOfPinnedObject();
return new MemoryHandle(ptr, this.pinHandle);
}
/// <inheritdoc />
public override void Unpin()
{
if (this.pinHandle.IsAllocated)
{
this.pinHandle.Free();
}
}
/// <summary>
/// Gets the object that should be pinned.
/// </summary>
/// <returns>The pinnable <see cref="object"/>.</returns>
protected abstract object GetPinnableObject();
}
}

39
src/ImageSharp/Memory/Allocators/MemoryAllocator.cs

@ -0,0 +1,39 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Memory managers are used to allocate memory for image processing operations.
/// </summary>
public abstract class MemoryAllocator
{
/// <summary>
/// Allocates an <see cref="IMemoryOwner{T}" />, holding a <see cref="System.Memory{T}"/> of length <paramref name="length"/>.
/// </summary>
/// <typeparam name="T">Type of the data stored in the buffer.</typeparam>
/// <param name="length">Size of the buffer to allocate.</param>
/// <param name="options">The allocation options.</param>
/// <returns>A buffer of values of type <typeparamref name="T"/>.</returns>
public abstract IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
where T : struct;
/// <summary>
/// Allocates an <see cref="IManagedByteBuffer"/>.
/// </summary>
/// <param name="length">The requested buffer length.</param>
/// <param name="options">The allocation options.</param>
/// <returns>The <see cref="IManagedByteBuffer"/>.</returns>
public abstract IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options = AllocationOptions.None);
/// <summary>
/// Releases all retained resources not being in use.
/// Eg: by resetting array pools and letting GC to free the arrays.
/// </summary>
public virtual void ReleaseRetainedResources()
{
}
}
}

30
src/ImageSharp/Memory/Allocators/SimpleGcMemoryAllocator.cs

@ -0,0 +1,30 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
using SixLabors.ImageSharp.Memory.Internals;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Implements <see cref="MemoryAllocator"/> by newing up arrays by the GC on every allocation requests.
/// </summary>
public sealed class SimpleGcMemoryAllocator : MemoryAllocator
{
/// <inheritdoc />
public override IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
{
Guard.MustBeGreaterThanOrEqualTo(length, 0, nameof(length));
return new BasicArrayBuffer<T>(new T[length]);
}
/// <inheritdoc />
public override IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options = AllocationOptions.None)
{
Guard.MustBeGreaterThanOrEqualTo(length, 0, nameof(length));
return new BasicByteBuffer(new byte[length]);
}
}
}

2
src/ImageSharp/Memory/Buffer2DExtensions.cs

@ -6,8 +6,6 @@ using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>

4
src/ImageSharp/Memory/Buffer2D{T}.cs

@ -4,8 +4,6 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
@ -16,7 +14,7 @@ namespace SixLabors.ImageSharp.Memory
/// Before RC1, this class might be target of API changes, use it on your own risk!
/// </remarks>
/// <typeparam name="T">The value type.</typeparam>
// TODO: Consider moving this type to the SixLabors.Memory namespace (SixLabors.Core).
// TODO: Consider moving this type to the SixLabors.ImageSharp.Memory namespace (SixLabors.Core).
public sealed class Buffer2D<T> : IDisposable
where T : struct
{

2
src/ImageSharp/Memory/BufferArea{T}.cs

@ -3,8 +3,6 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>

3
src/ImageSharp/Memory/MemoryAllocatorExtensions.cs

@ -3,9 +3,6 @@
using System.Buffers;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>

2
src/ImageSharp/Memory/MemorySource.cs

@ -4,8 +4,6 @@
using System;
using System.Buffers;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>

5
src/ImageSharp/Memory/RowInterval.cs

@ -1,10 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
@ -13,7 +11,6 @@ namespace SixLabors.ImageSharp.Memory
/// <remarks>
/// Before RC1, this class might be target of API changes, use it on your own risk!
/// </remarks>
// TODO: Consider moving this type to the SixLabors.Memory namespace (SixLabors.Core).
public readonly struct RowInterval : IEquatable<RowInterval>
{
/// <summary>

1
src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{

1
src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs

@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;
using System.Text;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{

1
src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs

@ -5,7 +5,6 @@ using System;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Text;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{

2
src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.Number.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
/// <content/>

2
src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.NumberArray.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
/// <content/>

2
src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.Rational.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
/// <content/>

2
src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.RationalArray.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
/// <content/>

2
src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.SignedRational.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
/// <content/>

2
src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.SignedRationalArray.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
/// <content/>

1
src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumber.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System.Globalization;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{

2
src/ImageSharp/Metadata/Profiles/Exif/Values/ExifNumberArray.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
internal sealed class ExifNumberArray : ExifArrayValue<Number>

1
src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRational.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System.Globalization;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{

1
src/ImageSharp/Metadata/Profiles/Exif/Values/ExifRationalArray.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{

1
src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedRational.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System.Globalization;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{

2
src/ImageSharp/Metadata/Profiles/Exif/Values/ExifSignedRationalArray.cs

@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
internal sealed class ExifSignedRationalArray : ExifArrayValue<SignedRational>

1
src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Matrix.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
{

2
src/ImageSharp/Metadata/Profiles/ICC/MultiProcessElements/IccMatrixProcessElement.cs

@ -3,8 +3,6 @@
using System;
using SixLabors.ImageSharp.Primitives;
namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
{
/// <summary>

112
src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs

@ -4,10 +4,6 @@
// <auto-generated />
using System;
using System.Numerics;
using System.Buffers;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
@ -26,7 +22,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// A pixel blender that implements the "NormalSrc" composition equation.
/// </summary>
@ -65,7 +60,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplySrc" composition equation.
/// </summary>
@ -104,7 +98,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddSrc" composition equation.
/// </summary>
@ -143,7 +136,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractSrc" composition equation.
/// </summary>
@ -182,7 +174,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenSrc" composition equation.
/// </summary>
@ -221,7 +212,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenSrc" composition equation.
/// </summary>
@ -260,7 +250,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenSrc" composition equation.
/// </summary>
@ -299,7 +288,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlaySrc" composition equation.
/// </summary>
@ -338,7 +326,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightSrc" composition equation.
/// </summary>
@ -377,7 +364,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalSrcAtop" composition equation.
/// </summary>
@ -416,7 +402,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplySrcAtop" composition equation.
/// </summary>
@ -455,7 +440,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddSrcAtop" composition equation.
/// </summary>
@ -494,7 +478,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractSrcAtop" composition equation.
/// </summary>
@ -533,7 +516,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenSrcAtop" composition equation.
/// </summary>
@ -572,7 +554,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenSrcAtop" composition equation.
/// </summary>
@ -611,7 +592,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenSrcAtop" composition equation.
/// </summary>
@ -650,7 +630,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlaySrcAtop" composition equation.
/// </summary>
@ -689,7 +668,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightSrcAtop" composition equation.
/// </summary>
@ -728,7 +706,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalSrcOver" composition equation.
/// </summary>
@ -767,7 +744,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplySrcOver" composition equation.
/// </summary>
@ -806,7 +782,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddSrcOver" composition equation.
/// </summary>
@ -845,7 +820,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractSrcOver" composition equation.
/// </summary>
@ -884,7 +858,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenSrcOver" composition equation.
/// </summary>
@ -923,7 +896,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenSrcOver" composition equation.
/// </summary>
@ -962,7 +934,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenSrcOver" composition equation.
/// </summary>
@ -1001,7 +972,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlaySrcOver" composition equation.
/// </summary>
@ -1040,7 +1010,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightSrcOver" composition equation.
/// </summary>
@ -1079,7 +1048,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalSrcIn" composition equation.
/// </summary>
@ -1118,7 +1086,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplySrcIn" composition equation.
/// </summary>
@ -1157,7 +1124,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddSrcIn" composition equation.
/// </summary>
@ -1196,7 +1162,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractSrcIn" composition equation.
/// </summary>
@ -1235,7 +1200,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenSrcIn" composition equation.
/// </summary>
@ -1274,7 +1238,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenSrcIn" composition equation.
/// </summary>
@ -1313,7 +1276,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenSrcIn" composition equation.
/// </summary>
@ -1352,7 +1314,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlaySrcIn" composition equation.
/// </summary>
@ -1391,7 +1352,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightSrcIn" composition equation.
/// </summary>
@ -1430,7 +1390,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalSrcOut" composition equation.
/// </summary>
@ -1469,7 +1428,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplySrcOut" composition equation.
/// </summary>
@ -1508,7 +1466,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddSrcOut" composition equation.
/// </summary>
@ -1547,7 +1504,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractSrcOut" composition equation.
/// </summary>
@ -1586,7 +1542,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenSrcOut" composition equation.
/// </summary>
@ -1625,7 +1580,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenSrcOut" composition equation.
/// </summary>
@ -1664,7 +1618,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenSrcOut" composition equation.
/// </summary>
@ -1703,7 +1656,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlaySrcOut" composition equation.
/// </summary>
@ -1742,7 +1694,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightSrcOut" composition equation.
/// </summary>
@ -1781,7 +1732,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalDest" composition equation.
/// </summary>
@ -1820,7 +1770,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplyDest" composition equation.
/// </summary>
@ -1859,7 +1808,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddDest" composition equation.
/// </summary>
@ -1898,7 +1846,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractDest" composition equation.
/// </summary>
@ -1937,7 +1884,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenDest" composition equation.
/// </summary>
@ -1976,7 +1922,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenDest" composition equation.
/// </summary>
@ -2015,7 +1960,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenDest" composition equation.
/// </summary>
@ -2054,7 +1998,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlayDest" composition equation.
/// </summary>
@ -2093,7 +2036,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightDest" composition equation.
/// </summary>
@ -2132,7 +2074,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalDestAtop" composition equation.
/// </summary>
@ -2171,7 +2112,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplyDestAtop" composition equation.
/// </summary>
@ -2210,7 +2150,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddDestAtop" composition equation.
/// </summary>
@ -2249,7 +2188,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractDestAtop" composition equation.
/// </summary>
@ -2288,7 +2226,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenDestAtop" composition equation.
/// </summary>
@ -2327,7 +2264,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenDestAtop" composition equation.
/// </summary>
@ -2366,7 +2302,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenDestAtop" composition equation.
/// </summary>
@ -2405,7 +2340,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlayDestAtop" composition equation.
/// </summary>
@ -2444,7 +2378,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightDestAtop" composition equation.
/// </summary>
@ -2483,7 +2416,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalDestOver" composition equation.
/// </summary>
@ -2522,7 +2454,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplyDestOver" composition equation.
/// </summary>
@ -2561,7 +2492,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddDestOver" composition equation.
/// </summary>
@ -2600,7 +2530,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractDestOver" composition equation.
/// </summary>
@ -2639,7 +2568,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenDestOver" composition equation.
/// </summary>
@ -2678,7 +2606,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenDestOver" composition equation.
/// </summary>
@ -2717,7 +2644,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenDestOver" composition equation.
/// </summary>
@ -2756,7 +2682,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlayDestOver" composition equation.
/// </summary>
@ -2795,7 +2720,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightDestOver" composition equation.
/// </summary>
@ -2834,7 +2758,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalDestIn" composition equation.
/// </summary>
@ -2873,7 +2796,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplyDestIn" composition equation.
/// </summary>
@ -2912,7 +2834,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddDestIn" composition equation.
/// </summary>
@ -2951,7 +2872,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractDestIn" composition equation.
/// </summary>
@ -2990,7 +2910,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenDestIn" composition equation.
/// </summary>
@ -3029,7 +2948,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenDestIn" composition equation.
/// </summary>
@ -3068,7 +2986,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenDestIn" composition equation.
/// </summary>
@ -3107,7 +3024,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlayDestIn" composition equation.
/// </summary>
@ -3146,7 +3062,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightDestIn" composition equation.
/// </summary>
@ -3185,7 +3100,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalDestOut" composition equation.
/// </summary>
@ -3224,7 +3138,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplyDestOut" composition equation.
/// </summary>
@ -3263,7 +3176,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddDestOut" composition equation.
/// </summary>
@ -3302,7 +3214,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractDestOut" composition equation.
/// </summary>
@ -3341,7 +3252,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenDestOut" composition equation.
/// </summary>
@ -3380,7 +3290,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenDestOut" composition equation.
/// </summary>
@ -3419,7 +3328,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenDestOut" composition equation.
/// </summary>
@ -3458,7 +3366,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlayDestOut" composition equation.
/// </summary>
@ -3497,7 +3404,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightDestOut" composition equation.
/// </summary>
@ -3536,7 +3442,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalClear" composition equation.
/// </summary>
@ -3575,7 +3480,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplyClear" composition equation.
/// </summary>
@ -3614,7 +3518,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddClear" composition equation.
/// </summary>
@ -3653,7 +3556,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractClear" composition equation.
/// </summary>
@ -3692,7 +3594,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenClear" composition equation.
/// </summary>
@ -3731,7 +3632,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenClear" composition equation.
/// </summary>
@ -3770,7 +3670,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenClear" composition equation.
/// </summary>
@ -3809,7 +3708,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlayClear" composition equation.
/// </summary>
@ -3848,7 +3746,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightClear" composition equation.
/// </summary>
@ -3887,7 +3784,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "NormalXor" composition equation.
/// </summary>
@ -3926,7 +3822,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "MultiplyXor" composition equation.
/// </summary>
@ -3965,7 +3860,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "AddXor" composition equation.
/// </summary>
@ -4004,7 +3898,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "SubtractXor" composition equation.
/// </summary>
@ -4043,7 +3936,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "ScreenXor" composition equation.
/// </summary>
@ -4082,7 +3974,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "DarkenXor" composition equation.
/// </summary>
@ -4121,7 +4012,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "LightenXor" composition equation.
/// </summary>
@ -4160,7 +4050,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "OverlayXor" composition equation.
/// </summary>
@ -4199,7 +4088,6 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
}
}
/// <summary>
/// A pixel blender that implements the "HardLightXor" composition equation.
/// </summary>

4
src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt

@ -14,10 +14,6 @@
// <auto-generated />
using System;
using System.Numerics;
using System.Buffers;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{

2
src/ImageSharp/Primitives/ColorMatrix.cs

@ -6,7 +6,7 @@ using System;
using System.Globalization;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// A structure encapsulating a 5x4 matrix used for transforming the color and alpha components of an image.

2
src/ImageSharp/Primitives/Complex64.cs

@ -5,7 +5,7 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents a complex number, where the real and imaginary parts are stored as <see cref="float"/> values.

2
src/ImageSharp/Primitives/ComplexVector4.cs

@ -5,7 +5,7 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// A vector with 4 values of type <see cref="Complex64"/>.

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

@ -4,9 +4,8 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents a dense matrix with arbitrary elements.

2
src/ImageSharp/Primitives/LongRational.cs

@ -5,7 +5,7 @@ using System;
using System.Globalization;
using System.Text;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents a number that can be expressed as a fraction.

101
src/ImageSharp/Primitives/Matrix3x2Extensions.cs

@ -0,0 +1,101 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Extension methods for the <see cref="Matrix3x2"/> struct.
/// </summary>
public static class Matrix3x2Extensions
{
/// <summary>
/// Creates a translation matrix from the given vector.
/// </summary>
/// <param name="position">The translation position.</param>
/// <returns>A translation matrix.</returns>
public static Matrix3x2 CreateTranslation(PointF position) => Matrix3x2.CreateTranslation(position);
/// <summary>
/// Creates a scale matrix that is offset by a given center point.
/// </summary>
/// <param name="xScale">Value to scale by on the X-axis.</param>
/// <param name="yScale">Value to scale by on the Y-axis.</param>
/// <param name="centerPoint">The center point.</param>
/// <returns>A scaling matrix.</returns>
public static Matrix3x2 CreateScale(float xScale, float yScale, PointF centerPoint) => Matrix3x2.CreateScale(xScale, yScale, centerPoint);
/// <summary>
/// Creates a scale matrix from the given vector scale.
/// </summary>
/// <param name="scales">The scale to use.</param>
/// <returns>A scaling matrix.</returns>
public static Matrix3x2 CreateScale(SizeF scales) => Matrix3x2.CreateScale(scales);
/// <summary>
/// Creates a scale matrix from the given vector scale with an offset from the given center point.
/// </summary>
/// <param name="scales">The scale to use.</param>
/// <param name="centerPoint">The center offset.</param>
/// <returns>A scaling matrix.</returns>
public static Matrix3x2 CreateScale(SizeF scales, PointF centerPoint) => Matrix3x2.CreateScale(scales, centerPoint);
/// <summary>
/// Creates a scale matrix that scales uniformly with the given scale with an offset from the given center.
/// </summary>
/// <param name="scale">The uniform scale to use.</param>
/// <param name="centerPoint">The center offset.</param>
/// <returns>A scaling matrix.</returns>
public static Matrix3x2 CreateScale(float scale, PointF centerPoint) => Matrix3x2.CreateScale(scale, centerPoint);
/// <summary>
/// Creates a skew matrix from the given angles in degrees.
/// </summary>
/// <param name="degreesX">The X angle, in degrees.</param>
/// <param name="degreesY">The Y angle, in degrees.</param>
/// <returns>A skew matrix.</returns>
public static Matrix3x2 CreateSkewDegrees(float degreesX, float degreesY) => Matrix3x2.CreateSkew(GeometryUtilities.DegreeToRadian(degreesX), GeometryUtilities.DegreeToRadian(degreesY));
/// <summary>
/// Creates a skew matrix from the given angles in radians and a center point.
/// </summary>
/// <param name="radiansX">The X angle, in radians.</param>
/// <param name="radiansY">The Y angle, in radians.</param>
/// <param name="centerPoint">The center point.</param>
/// <returns>A skew matrix.</returns>
public static Matrix3x2 CreateSkew(float radiansX, float radiansY, PointF centerPoint) => Matrix3x2.CreateSkew(radiansX, radiansY, centerPoint);
/// <summary>
/// Creates a skew matrix from the given angles in degrees and a center point.
/// </summary>
/// <param name="degreesX">The X angle, in degrees.</param>
/// <param name="degreesY">The Y angle, in degrees.</param>
/// <param name="centerPoint">The center point.</param>
/// <returns>A skew matrix.</returns>
public static Matrix3x2 CreateSkewDegrees(float degreesX, float degreesY, PointF centerPoint) => Matrix3x2.CreateSkew(GeometryUtilities.DegreeToRadian(degreesX), GeometryUtilities.DegreeToRadian(degreesY), centerPoint);
/// <summary>
/// Creates a rotation matrix using the given rotation in degrees.
/// </summary>
/// <param name="degrees">The amount of rotation, in degrees.</param>
/// <returns>A rotation matrix.</returns>
public static Matrix3x2 CreateRotationDegrees(float degrees) => Matrix3x2.CreateRotation(GeometryUtilities.DegreeToRadian(degrees));
/// <summary>
/// Creates a rotation matrix using the given rotation in radians and a center point.
/// </summary>
/// <param name="radians">The amount of rotation, in radians.</param>
/// <param name="centerPoint">The center point.</param>
/// <returns>A rotation matrix.</returns>
public static Matrix3x2 CreateRotation(float radians, PointF centerPoint) => Matrix3x2.CreateRotation(radians, centerPoint);
/// <summary>
/// Creates a rotation matrix using the given rotation in degrees and a center point.
/// </summary>
/// <param name="degrees">The amount of rotation, in degrees.</param>
/// <param name="centerPoint">The center point.</param>
/// <returns>A rotation matrix.</returns>
public static Matrix3x2 CreateRotationDegrees(float degrees, PointF centerPoint) => Matrix3x2.CreateRotation(GeometryUtilities.DegreeToRadian(degrees), centerPoint);
}
}

2
src/ImageSharp/Primitives/Number.cs

@ -5,7 +5,7 @@ using System;
using System.Globalization;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents an integral number.

288
src/ImageSharp/Primitives/Point.cs

@ -0,0 +1,288 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents an ordered pair of integer x- and y-coordinates that defines a point in
/// a two-dimensional plane.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public struct Point : IEquatable<Point>
{
/// <summary>
/// Represents a <see cref="Point"/> that has X and Y values set to zero.
/// </summary>
public static readonly Point Empty = default;
/// <summary>
/// Initializes a new instance of the <see cref="Point"/> struct.
/// </summary>
/// <param name="value">The horizontal and vertical position of the point.</param>
public Point(int value)
: this()
{
this.X = LowInt16(value);
this.Y = HighInt16(value);
}
/// <summary>
/// Initializes a new instance of the <see cref="Point"/> struct.
/// </summary>
/// <param name="x">The horizontal position of the point.</param>
/// <param name="y">The vertical position of the point.</param>
public Point(int x, int y)
: this()
{
this.X = x;
this.Y = y;
}
/// <summary>
/// Initializes a new instance of the <see cref="Point"/> struct from the given <see cref="Size"/>.
/// </summary>
/// <param name="size">The size.</param>
public Point(Size size)
{
this.X = size.Width;
this.Y = size.Height;
}
/// <summary>
/// Gets or sets the x-coordinate of this <see cref="Point"/>.
/// </summary>
public int X { get; set; }
/// <summary>
/// Gets or sets the y-coordinate of this <see cref="Point"/>.
/// </summary>
public int Y { get; set; }
/// <summary>
/// Gets a value indicating whether this <see cref="Point"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Creates a <see cref="PointF"/> with the coordinates of the specified <see cref="Point"/>.
/// </summary>
/// <param name="point">The point.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator PointF(Point point) => new PointF(point.X, point.Y);
/// <summary>
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="Point"/>.
/// </summary>
/// <param name="point">The point.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Vector2(Point point) => new Vector2(point.X, point.Y);
/// <summary>
/// Creates a <see cref="Size"/> with the coordinates of the specified <see cref="Point"/>.
/// </summary>
/// <param name="point">The point.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Size(Point point) => new Size(point.X, point.Y);
/// <summary>
/// Negates the given point by multiplying all values by -1.
/// </summary>
/// <param name="value">The source point.</param>
/// <returns>The negated point.</returns>
public static Point operator -(Point value) => new Point(-value.X, -value.Y);
/// <summary>
/// Translates a <see cref="Point"/> by a given <see cref="Size"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>
/// The <see cref="Point"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point operator +(Point point, Size size) => Add(point, size);
/// <summary>
/// Translates a <see cref="Point"/> by the negative of a given <see cref="Size"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point operator -(Point point, Size size) => Subtract(point, size);
/// <summary>
/// Multiplies <see cref="Point"/> by a <see cref="int"/> producing <see cref="Point"/>.
/// </summary>
/// <param name="left">Multiplier of type <see cref="int"/>.</param>
/// <param name="right">Multiplicand of type <see cref="Point"/>.</param>
/// <returns>Product of type <see cref="Point"/>.</returns>
public static Point operator *(int left, Point right) => Multiply(right, left);
/// <summary>
/// Multiplies <see cref="Point"/> by a <see cref="int"/> producing <see cref="Point"/>.
/// </summary>
/// <param name="left">Multiplicand of type <see cref="Point"/>.</param>
/// <param name="right">Multiplier of type <see cref="int"/>.</param>
/// <returns>Product of type <see cref="Point"/>.</returns>
public static Point operator *(Point left, int right) => Multiply(left, right);
/// <summary>
/// Divides <see cref="Point"/> by a <see cref="int"/> producing <see cref="Point"/>.
/// </summary>
/// <param name="left">Dividend of type <see cref="Point"/>.</param>
/// <param name="right">Divisor of type <see cref="int"/>.</param>
/// <returns>Result of type <see cref="Point"/>.</returns>
public static Point operator /(Point left, int right)
=> new Point(left.X / right, left.Y / right);
/// <summary>
/// Compares two <see cref="Point"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Point"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Point"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Point left, Point right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Point"/> objects for inequality.
/// </summary>
/// <param name="left">The <see cref="Point"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Point"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Point left, Point right) => !left.Equals(right);
/// <summary>
/// Translates a <see cref="Point"/> by the negative of a given <see cref="Size"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Add(Point point, Size size) => new Point(unchecked(point.X + size.Width), unchecked(point.Y + size.Height));
/// <summary>
/// Translates a <see cref="Point"/> by the negative of a given value.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="value">The value on the right hand of the operand.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Multiply(Point point, int value) => new Point(unchecked(point.X * value), unchecked(point.Y * value));
/// <summary>
/// Translates a <see cref="Point"/> by the negative of a given <see cref="Size"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Subtract(Point point, Size size) => new Point(unchecked(point.X - size.Width), unchecked(point.Y - size.Height));
/// <summary>
/// Converts a <see cref="PointF"/> to a <see cref="Point"/> by performing a ceiling operation on all the coordinates.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Ceiling(PointF point) => new Point(unchecked((int)MathF.Ceiling(point.X)), unchecked((int)MathF.Ceiling(point.Y)));
/// <summary>
/// Converts a <see cref="PointF"/> to a <see cref="Point"/> by performing a round operation on all the coordinates.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Round(PointF point) => new Point(unchecked((int)MathF.Round(point.X)), unchecked((int)MathF.Round(point.Y)));
/// <summary>
/// Converts a <see cref="Vector2"/> to a <see cref="Point"/> by performing a round operation on all the coordinates.
/// </summary>
/// <param name="vector">The vector.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Round(Vector2 vector) => new Point(unchecked((int)MathF.Round(vector.X)), unchecked((int)MathF.Round(vector.Y)));
/// <summary>
/// Converts a <see cref="PointF"/> to a <see cref="Point"/> by performing a truncate operation on all the coordinates.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Truncate(PointF point) => new Point(unchecked((int)point.X), unchecked((int)point.Y));
/// <summary>
/// Transforms a point by a specified 3x2 matrix.
/// </summary>
/// <param name="point">The point to transform.</param>
/// <param name="matrix">The transformation matrix used.</param>
/// <returns>The transformed <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Transform(Point point, Matrix3x2 matrix) => Round(Vector2.Transform(new Vector2(point.X, point.Y), matrix));
/// <summary>
/// Deconstructs this point into two integers.
/// </summary>
/// <param name="x">The out value for X.</param>
/// <param name="y">The out value for Y.</param>
public void Deconstruct(out int x, out int y)
{
x = this.X;
y = this.Y;
}
/// <summary>
/// Translates this <see cref="Point"/> by the specified amount.
/// </summary>
/// <param name="dx">The amount to offset the x-coordinate.</param>
/// <param name="dy">The amount to offset the y-coordinate.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Offset(int dx, int dy)
{
unchecked
{
this.X += dx;
this.Y += dy;
}
}
/// <summary>
/// Translates this <see cref="Point"/> by the specified amount.
/// </summary>
/// <param name="point">The <see cref="Point"/> used offset this <see cref="Point"/>.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Offset(Point point) => this.Offset(point.X, point.Y);
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.X, this.Y);
/// <inheritdoc/>
public override string ToString() => $"Point [ X={this.X}, Y={this.Y} ]";
/// <inheritdoc/>
public override bool Equals(object obj) => obj is Point other && this.Equals(other);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Point other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
private static short HighInt16(int n) => unchecked((short)((n >> 16) & 0xffff));
private static short LowInt16(int n) => unchecked((short)(n & 0xffff));
}
}

293
src/ImageSharp/Primitives/PointF.cs

@ -0,0 +1,293 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents an ordered pair of single precision floating point x- and y-coordinates that defines a point in
/// a two-dimensional plane.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public struct PointF : IEquatable<PointF>
{
/// <summary>
/// Represents a <see cref="PointF"/> that has X and Y values set to zero.
/// </summary>
public static readonly PointF Empty = default;
/// <summary>
/// Initializes a new instance of the <see cref="PointF"/> struct.
/// </summary>
/// <param name="x">The horizontal position of the point.</param>
/// <param name="y">The vertical position of the point.</param>
public PointF(float x, float y)
: this()
{
this.X = x;
this.Y = y;
}
/// <summary>
/// Initializes a new instance of the <see cref="PointF"/> struct from the given <see cref="SizeF"/>.
/// </summary>
/// <param name="size">The size.</param>
public PointF(SizeF size)
{
this.X = size.Width;
this.Y = size.Height;
}
/// <summary>
/// Gets or sets the x-coordinate of this <see cref="PointF"/>.
/// </summary>
public float X { get; set; }
/// <summary>
/// Gets or sets the y-coordinate of this <see cref="PointF"/>.
/// </summary>
public float Y { get; set; }
/// <summary>
/// Gets a value indicating whether this <see cref="PointF"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
/// </summary>
/// <param name="vector">The vector.</param>
/// <returns>
/// The <see cref="Vector2"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator PointF(Vector2 vector) => new PointF(vector.X, vector.Y);
/// <summary>
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The <see cref="Vector2"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Vector2(PointF point) => new Vector2(point.X, point.Y);
/// <summary>
/// Creates a <see cref="Point"/> with the coordinates of the specified <see cref="PointF"/> by truncating each of the coordinates.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The <see cref="Point"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Point(PointF point) => Point.Truncate(point);
/// <summary>
/// Negates the given point by multiplying all values by -1.
/// </summary>
/// <param name="value">The source point.</param>
/// <returns>The negated point.</returns>
public static PointF operator -(PointF value) => new PointF(-value.X, -value.Y);
/// <summary>
/// Translates a <see cref="PointF"/> by a given <see cref="SizeF"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>
/// The <see cref="PointF"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF operator +(PointF point, SizeF size) => Add(point, size);
/// <summary>
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>The <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF operator -(PointF point, PointF size) => Subtract(point, size);
/// <summary>
/// Translates a <see cref="PointF"/> by a given <see cref="SizeF"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>
/// The <see cref="PointF"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF operator +(PointF point, PointF size) => Add(point, size);
/// <summary>
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>The <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF operator -(PointF point, SizeF size) => Subtract(point, size);
/// <summary>
/// Multiplies <see cref="PointF"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Multiplier of type <see cref="float"/>.</param>
/// <param name="right">Multiplicand of type <see cref="SizeF"/>.</param>
/// <returns>Product of type <see cref="SizeF"/>.</returns>
public static PointF operator *(float left, PointF right) => Multiply(right, left);
/// <summary>
/// Multiplies <see cref="PointF"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Multiplicand of type <see cref="PointF"/>.</param>
/// <param name="right">Multiplier of type <see cref="float"/>.</param>
/// <returns>Product of type <see cref="SizeF"/>.</returns>
public static PointF operator *(PointF left, float right) => Multiply(left, right);
/// <summary>
/// Divides <see cref="PointF"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Dividend of type <see cref="PointF"/>.</param>
/// <param name="right">Divisor of type <see cref="int"/>.</param>
/// <returns>Result of type <see cref="PointF"/>.</returns>
public static PointF operator /(PointF left, float right)
=> new PointF(left.X / right, left.Y / right);
/// <summary>
/// Compares two <see cref="PointF"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="PointF"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="PointF"/> on the right side of the operand.
/// </param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(PointF left, PointF right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="PointF"/> objects for inequality.
/// </summary>
/// <param name="left">
/// The <see cref="PointF"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="PointF"/> on the right side of the operand.
/// </param>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(PointF left, PointF right) => !left.Equals(right);
/// <summary>
/// Translates a <see cref="PointF"/> by the given <see cref="SizeF"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>The <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF Add(PointF point, SizeF size) => new PointF(point.X + size.Width, point.Y + size.Height);
/// <summary>
/// Translates a <see cref="PointF"/> by the given <see cref="PointF"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="pointb">The point on the right hand of the operand.</param>
/// <returns>The <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF Add(PointF point, PointF pointb) => new PointF(point.X + pointb.X, point.Y + pointb.Y);
/// <summary>
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="size">The size on the right hand of the operand.</param>
/// <returns>The <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF Subtract(PointF point, SizeF size) => new PointF(point.X - size.Width, point.Y - size.Height);
/// <summary>
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="PointF"/>.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="pointb">The point on the right hand of the operand.</param>
/// <returns>The <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF Subtract(PointF point, PointF pointb) => new PointF(point.X - pointb.X, point.Y - pointb.Y);
/// <summary>
/// Translates a <see cref="PointF"/> by the multiplying the X and Y by the given value.
/// </summary>
/// <param name="point">The point on the left hand of the operand.</param>
/// <param name="right">The value on the right hand of the operand.</param>
/// <returns>The <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF Multiply(PointF point, float right) => new PointF(point.X * right, point.Y * right);
/// <summary>
/// Transforms a point by a specified 3x2 matrix.
/// </summary>
/// <param name="point">The point to transform.</param>
/// <param name="matrix">The transformation matrix used.</param>
/// <returns>The transformed <see cref="PointF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF Transform(PointF point, Matrix3x2 matrix) => Vector2.Transform(point, matrix);
/// <summary>
/// Deconstructs this point into two floats.
/// </summary>
/// <param name="x">The out value for X.</param>
/// <param name="y">The out value for Y.</param>
public void Deconstruct(out float x, out float y)
{
x = this.X;
y = this.Y;
}
/// <summary>
/// Translates this <see cref="PointF"/> by the specified amount.
/// </summary>
/// <param name="dx">The amount to offset the x-coordinate.</param>
/// <param name="dy">The amount to offset the y-coordinate.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Offset(float dx, float dy)
{
this.X += dx;
this.Y += dy;
}
/// <summary>
/// Translates this <see cref="PointF"/> by the specified amount.
/// </summary>
/// <param name="point">The <see cref="PointF"/> used offset this <see cref="PointF"/>.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Offset(PointF point) => this.Offset(point.X, point.Y);
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.X, this.Y);
/// <inheritdoc/>
public override string ToString() => $"PointF [ X={this.X}, Y={this.Y} ]";
/// <inheritdoc/>
public override bool Equals(object obj) => obj is PointF && this.Equals((PointF)obj);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(PointF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y);
}
}

2
src/ImageSharp/Primitives/Rational.cs

@ -4,7 +4,7 @@
using System;
using System.Globalization;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents a number that can be expressed as a fraction.

463
src/ImageSharp/Primitives/Rectangle.cs

@ -0,0 +1,463 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Stores a set of four integers that represent the location and size of a rectangle.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public struct Rectangle : IEquatable<Rectangle>
{
/// <summary>
/// Represents a <see cref="Rectangle"/> that has X, Y, Width, and Height values set to zero.
/// </summary>
public static readonly Rectangle Empty = default;
/// <summary>
/// Initializes a new instance of the <see cref="Rectangle"/> struct.
/// </summary>
/// <param name="x">The horizontal position of the rectangle.</param>
/// <param name="y">The vertical position of the rectangle.</param>
/// <param name="width">The width of the rectangle.</param>
/// <param name="height">The height of the rectangle.</param>
public Rectangle(int x, int y, int width, int height)
{
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
}
/// <summary>
/// Initializes a new instance of the <see cref="Rectangle"/> struct.
/// </summary>
/// <param name="point">
/// The <see cref="Point"/> which specifies the rectangles point in a two-dimensional plane.
/// </param>
/// <param name="size">
/// The <see cref="Size"/> which specifies the rectangles height and width.
/// </param>
public Rectangle(Point point, Size size)
{
this.X = point.X;
this.Y = point.Y;
this.Width = size.Width;
this.Height = size.Height;
}
/// <summary>
/// Gets or sets the x-coordinate of this <see cref="Rectangle"/>.
/// </summary>
public int X { get; set; }
/// <summary>
/// Gets or sets the y-coordinate of this <see cref="Rectangle"/>.
/// </summary>
public int Y { get; set; }
/// <summary>
/// Gets or sets the width of this <see cref="Rectangle"/>.
/// </summary>
public int Width { get; set; }
/// <summary>
/// Gets or sets the height of this <see cref="Rectangle"/>.
/// </summary>
public int Height { get; set; }
/// <summary>
/// Gets or sets the coordinates of the upper-left corner of the rectangular region represented by this <see cref="Rectangle"/>.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public Point Location
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new Point(this.X, this.Y);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.X = value.X;
this.Y = value.Y;
}
}
/// <summary>
/// Gets or sets the size of this <see cref="Rectangle"/>.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public Size Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new Size(this.Width, this.Height);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.Width = value.Width;
this.Height = value.Height;
}
}
/// <summary>
/// Gets a value indicating whether this <see cref="Rectangle"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Gets the y-coordinate of the top edge of this <see cref="Rectangle"/>.
/// </summary>
public int Top => this.Y;
/// <summary>
/// Gets the x-coordinate of the right edge of this <see cref="Rectangle"/>.
/// </summary>
public int Right
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => unchecked(this.X + this.Width);
}
/// <summary>
/// Gets the y-coordinate of the bottom edge of this <see cref="Rectangle"/>.
/// </summary>
public int Bottom
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => unchecked(this.Y + this.Height);
}
/// <summary>
/// Gets the x-coordinate of the left edge of this <see cref="Rectangle"/>.
/// </summary>
public int Left => this.X;
/// <summary>
/// Creates a <see cref="RectangleF"/> with the coordinates of the specified <see cref="Rectangle"/>.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator RectangleF(Rectangle rectangle) => new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
/// <summary>
/// Creates a <see cref="Vector4"/> with the coordinates of the specified <see cref="Rectangle"/>.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Vector4(Rectangle rectangle) => new Vector4(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
/// <summary>
/// Compares two <see cref="Rectangle"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Rectangle"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Rectangle"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Rectangle left, Rectangle right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Rectangle"/> objects for inequality.
/// </summary>
/// <param name="left">The <see cref="Rectangle"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Rectangle"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rectangle left, Rectangle right) => !left.Equals(right);
/// <summary>
/// Creates a new <see cref="Rectangle"/> with the specified location and size. </summary>
/// <param name="left">The left coordinate of the rectangle.</param>
/// <param name="top">The top coordinate of the rectangle.</param>
/// <param name="right">The right coordinate of the rectangle.</param>
/// <param name="bottom">The bottom coordinate of the rectangle.</param>
/// <returns>The <see cref="Rectangle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// ReSharper disable once InconsistentNaming
public static Rectangle FromLTRB(int left, int top, int right, int bottom) => new Rectangle(left, top, unchecked(right - left), unchecked(bottom - top));
/// <summary>
/// Returns the center point of the given <see cref="Rectangle"/>.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Point Center(Rectangle rectangle) => new Point(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2));
/// <summary>
/// Creates a rectangle that represents the intersection between <paramref name="a"/> and
/// <paramref name="b"/>. If there is no intersection, an empty rectangle is returned.
/// </summary>
/// <param name="a">The first rectangle.</param>
/// <param name="b">The second rectangle.</param>
/// <returns>The <see cref="Rectangle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Rectangle Intersect(Rectangle a, Rectangle b)
{
int x1 = Math.Max(a.X, b.X);
int x2 = Math.Min(a.Right, b.Right);
int y1 = Math.Max(a.Y, b.Y);
int y2 = Math.Min(a.Bottom, b.Bottom);
if (x2 >= x1 && y2 >= y1)
{
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
return Empty;
}
/// <summary>
/// Creates a <see cref="Rectangle"/> that is inflated by the specified amount.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <param name="x">The amount to inflate the width by.</param>
/// <param name="y">The amount to inflate the height by.</param>
/// <returns>A new <see cref="Rectangle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Rectangle Inflate(Rectangle rectangle, int x, int y)
{
Rectangle r = rectangle;
r.Inflate(x, y);
return r;
}
/// <summary>
/// Converts a <see cref="RectangleF"/> to a <see cref="Rectangle"/> by performing a ceiling operation on all the coordinates.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <returns>The <see cref="Rectangle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Rectangle Ceiling(RectangleF rectangle)
{
unchecked
{
return new Rectangle(
(int)MathF.Ceiling(rectangle.X),
(int)MathF.Ceiling(rectangle.Y),
(int)MathF.Ceiling(rectangle.Width),
(int)MathF.Ceiling(rectangle.Height));
}
}
/// <summary>
/// Transforms a rectangle by the given matrix.
/// </summary>
/// <param name="rectangle">The source rectangle.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>A transformed rectangle.</returns>
public static RectangleF Transform(Rectangle rectangle, Matrix3x2 matrix)
{
PointF bottomRight = Point.Transform(new Point(rectangle.Right, rectangle.Bottom), matrix);
PointF topLeft = Point.Transform(rectangle.Location, matrix);
return new RectangleF(topLeft, new SizeF(bottomRight - topLeft));
}
/// <summary>
/// Converts a <see cref="RectangleF"/> to a <see cref="Rectangle"/> by performing a truncate operation on all the coordinates.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <returns>The <see cref="Rectangle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Rectangle Truncate(RectangleF rectangle)
{
unchecked
{
return new Rectangle(
(int)rectangle.X,
(int)rectangle.Y,
(int)rectangle.Width,
(int)rectangle.Height);
}
}
/// <summary>
/// Converts a <see cref="RectangleF"/> to a <see cref="Rectangle"/> by performing a round operation on all the coordinates.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <returns>The <see cref="Rectangle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Rectangle Round(RectangleF rectangle)
{
unchecked
{
return new Rectangle(
(int)MathF.Round(rectangle.X),
(int)MathF.Round(rectangle.Y),
(int)MathF.Round(rectangle.Width),
(int)MathF.Round(rectangle.Height));
}
}
/// <summary>
/// Creates a rectangle that represents the union between <paramref name="a"/> and <paramref name="b"/>.
/// </summary>
/// <param name="a">The first rectangle.</param>
/// <param name="b">The second rectangle.</param>
/// <returns>The <see cref="Rectangle"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Rectangle Union(Rectangle a, Rectangle b)
{
int x1 = Math.Min(a.X, b.X);
int x2 = Math.Max(a.Right, b.Right);
int y1 = Math.Min(a.Y, b.Y);
int y2 = Math.Max(a.Bottom, b.Bottom);
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
/// <summary>
/// Deconstructs this rectangle into four integers.
/// </summary>
/// <param name="x">The out value for X.</param>
/// <param name="y">The out value for Y.</param>
/// <param name="width">The out value for the width.</param>
/// <param name="height">The out value for the height.</param>
public void Deconstruct(out int x, out int y, out int width, out int height)
{
x = this.X;
y = this.Y;
width = this.Width;
height = this.Height;
}
/// <summary>
/// Creates a Rectangle that represents the intersection between this Rectangle and the <paramref name="rectangle"/>.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Intersect(Rectangle rectangle)
{
Rectangle result = Intersect(rectangle, this);
this.X = result.X;
this.Y = result.Y;
this.Width = result.Width;
this.Height = result.Height;
}
/// <summary>
/// Inflates this <see cref="Rectangle"/> by the specified amount.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Inflate(int width, int height)
{
unchecked
{
this.X -= width;
this.Y -= height;
this.Width += 2 * width;
this.Height += 2 * height;
}
}
/// <summary>
/// Inflates this <see cref="Rectangle"/> by the specified amount.
/// </summary>
/// <param name="size">The size.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Inflate(Size size) => this.Inflate(size.Width, size.Height);
/// <summary>
/// Determines if the specfied point is contained within the rectangular region defined by
/// this <see cref="Rectangle"/>.
/// </summary>
/// <param name="x">The x-coordinate of the given point.</param>
/// <param name="y">The y-coordinate of the given point.</param>
/// <returns>The <see cref="bool"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(int x, int y) => this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom;
/// <summary>
/// Determines if the specified point is contained within the rectangular region defined by this <see cref="Rectangle"/> .
/// </summary>
/// <param name="point">The point.</param>
/// <returns>The <see cref="bool"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(Point point) => this.Contains(point.X, point.Y);
/// <summary>
/// Determines if the rectangular region represented by <paramref name="rectangle"/> is entirely contained
/// within the rectangular region represented by this <see cref="Rectangle"/> .
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <returns>The <see cref="bool"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(Rectangle rectangle) =>
(this.X <= rectangle.X) && (rectangle.Right <= this.Right) &&
(this.Y <= rectangle.Y) && (rectangle.Bottom <= this.Bottom);
/// <summary>
/// Determines if the specfied <see cref="Rectangle"/> intersects the rectangular region defined by
/// this <see cref="Rectangle"/>.
/// </summary>
/// <param name="rectangle">The other Rectange. </param>
/// <returns>The <see cref="bool"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IntersectsWith(Rectangle rectangle) =>
(rectangle.X < this.Right) && (this.X < rectangle.Right) &&
(rectangle.Y < this.Bottom) && (this.Y < rectangle.Bottom);
/// <summary>
/// Adjusts the location of this rectangle by the specified amount.
/// </summary>
/// <param name="point">The point.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Offset(Point point) => this.Offset(point.X, point.Y);
/// <summary>
/// Adjusts the location of this rectangle by the specified amount.
/// </summary>
/// <param name="dx">The amount to offset the x-coordinate.</param>
/// <param name="dy">The amount to offset the y-coordinate.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Offset(int dx, int dy)
{
unchecked
{
this.X += dx;
this.Y += dy;
}
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(this.X, this.Y, this.Width, this.Height);
}
/// <inheritdoc/>
public override string ToString()
{
return $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]";
}
/// <inheritdoc/>
public override bool Equals(object obj) => obj is Rectangle other && this.Equals(other);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rectangle other) =>
this.X.Equals(other.X) &&
this.Y.Equals(other.Y) &&
this.Width.Equals(other.Width) &&
this.Height.Equals(other.Height);
}
}

396
src/ImageSharp/Primitives/RectangleF.cs

@ -0,0 +1,396 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Stores a set of four single precision floating points that represent the location and size of a rectangle.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public struct RectangleF : IEquatable<RectangleF>
{
/// <summary>
/// Represents a <see cref="RectangleF"/> that has X, Y, Width, and Height values set to zero.
/// </summary>
public static readonly RectangleF Empty = default;
/// <summary>
/// Initializes a new instance of the <see cref="RectangleF"/> struct.
/// </summary>
/// <param name="x">The horizontal position of the rectangle.</param>
/// <param name="y">The vertical position of the rectangle.</param>
/// <param name="width">The width of the rectangle.</param>
/// <param name="height">The height of the rectangle.</param>
public RectangleF(float x, float y, float width, float height)
{
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
}
/// <summary>
/// Initializes a new instance of the <see cref="RectangleF"/> struct.
/// </summary>
/// <param name="point">
/// The <see cref="Point"/> which specifies the rectangles point in a two-dimensional plane.
/// </param>
/// <param name="size">
/// The <see cref="Size"/> which specifies the rectangles height and width.
/// </param>
public RectangleF(PointF point, SizeF size)
{
this.X = point.X;
this.Y = point.Y;
this.Width = size.Width;
this.Height = size.Height;
}
/// <summary>
/// Gets or sets the x-coordinate of this <see cref="RectangleF"/>.
/// </summary>
public float X { get; set; }
/// <summary>
/// Gets or sets the y-coordinate of this <see cref="RectangleF"/>.
/// </summary>
public float Y { get; set; }
/// <summary>
/// Gets or sets the width of this <see cref="RectangleF"/>.
/// </summary>
public float Width { get; set; }
/// <summary>
/// Gets or sets the height of this <see cref="RectangleF"/>.
/// </summary>
public float Height { get; set; }
/// <summary>
/// Gets or sets the coordinates of the upper-left corner of the rectangular region represented by this <see cref="RectangleF"/>.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public PointF Location
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new PointF(this.X, this.Y);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.X = value.X;
this.Y = value.Y;
}
}
/// <summary>
/// Gets or sets the size of this <see cref="RectangleF"/>.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public SizeF Size
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new SizeF(this.Width, this.Height);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.Width = value.Width;
this.Height = value.Height;
}
}
/// <summary>
/// Gets a value indicating whether this <see cref="RectangleF"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => (this.Width <= 0) || (this.Height <= 0);
/// <summary>
/// Gets the y-coordinate of the top edge of this <see cref="RectangleF"/>.
/// </summary>
public float Top => this.Y;
/// <summary>
/// Gets the x-coordinate of the right edge of this <see cref="RectangleF"/>.
/// </summary>
public float Right
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.X + this.Width;
}
/// <summary>
/// Gets the y-coordinate of the bottom edge of this <see cref="RectangleF"/>.
/// </summary>
public float Bottom
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.Y + this.Height;
}
/// <summary>
/// Gets the x-coordinate of the left edge of this <see cref="RectangleF"/>.
/// </summary>
public float Left => this.X;
/// <summary>
/// Creates a <see cref="Rectangle"/> with the coordinates of the specified <see cref="RectangleF"/> by truncating each coordinate.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Rectangle(RectangleF rectangle) => Rectangle.Truncate(rectangle);
/// <summary>
/// Compares two <see cref="RectangleF"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="RectangleF"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="RectangleF"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(RectangleF left, RectangleF right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="RectangleF"/> objects for inequality.
/// </summary>
/// <param name="left">The <see cref="RectangleF"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="RectangleF"/> on the right side of the operand.</param>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(RectangleF left, RectangleF right) => !left.Equals(right);
/// <summary>
/// Creates a new <see cref="RectangleF"/> with the specified location and size. </summary>
/// <param name="left">The left coordinate of the rectangle.</param>
/// <param name="top">The top coordinate of the rectangle.</param>
/// <param name="right">The right coordinate of the rectangle.</param>
/// <param name="bottom">The bottom coordinate of the rectangle.</param>
/// <returns>The <see cref="RectangleF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// ReSharper disable once InconsistentNaming
public static RectangleF FromLTRB(float left, float top, float right, float bottom) => new RectangleF(left, top, right - left, bottom - top);
/// <summary>
/// Returns the center point of the given <see cref="RectangleF"/>.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <returns>The <see cref="Point"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static PointF Center(RectangleF rectangle) => new PointF(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2));
/// <summary>
/// Creates a rectangle that represents the intersection between <paramref name="a"/> and
/// <paramref name="b"/>. If there is no intersection, an empty rectangle is returned.
/// </summary>
/// <param name="a">The first rectangle.</param>
/// <param name="b">The second rectangle.</param>
/// <returns>The <see cref="RectangleF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static RectangleF Intersect(RectangleF a, RectangleF b)
{
float x1 = MathF.Max(a.X, b.X);
float x2 = MathF.Min(a.Right, b.Right);
float y1 = MathF.Max(a.Y, b.Y);
float y2 = MathF.Min(a.Bottom, b.Bottom);
if (x2 >= x1 && y2 >= y1)
{
return new RectangleF(x1, y1, x2 - x1, y2 - y1);
}
return Empty;
}
/// <summary>
/// Creates a <see cref="RectangleF"/> that is inflated by the specified amount.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <param name="x">The amount to inflate the width by.</param>
/// <param name="y">The amount to inflate the height by.</param>
/// <returns>A new <see cref="RectangleF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static RectangleF Inflate(RectangleF rectangle, float x, float y)
{
RectangleF r = rectangle;
r.Inflate(x, y);
return r;
}
/// <summary>
/// Transforms a rectangle by the given matrix.
/// </summary>
/// <param name="rectangle">The source rectangle.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>A transformed <see cref="RectangleF"/>.</returns>
public static RectangleF Transform(RectangleF rectangle, Matrix3x2 matrix)
{
PointF bottomRight = PointF.Transform(new PointF(rectangle.Right, rectangle.Bottom), matrix);
PointF topLeft = PointF.Transform(rectangle.Location, matrix);
return new RectangleF(topLeft, new SizeF(bottomRight - topLeft));
}
/// <summary>
/// Creates a rectangle that represents the union between <paramref name="a"/> and <paramref name="b"/>.
/// </summary>
/// <param name="a">The first rectangle.</param>
/// <param name="b">The second rectangle.</param>
/// <returns>The <see cref="RectangleF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static RectangleF Union(RectangleF a, RectangleF b)
{
float x1 = MathF.Min(a.X, b.X);
float x2 = MathF.Max(a.Right, b.Right);
float y1 = MathF.Min(a.Y, b.Y);
float y2 = MathF.Max(a.Bottom, b.Bottom);
return new RectangleF(x1, y1, x2 - x1, y2 - y1);
}
/// <summary>
/// Deconstructs this rectangle into four floats.
/// </summary>
/// <param name="x">The out value for X.</param>
/// <param name="y">The out value for Y.</param>
/// <param name="width">The out value for the width.</param>
/// <param name="height">The out value for the height.</param>
public void Deconstruct(out float x, out float y, out float width, out float height)
{
x = this.X;
y = this.Y;
width = this.Width;
height = this.Height;
}
/// <summary>
/// Creates a RectangleF that represents the intersection between this RectangleF and the <paramref name="rectangle"/>.
/// </summary>
/// <param name="rectangle">The rectangle.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Intersect(RectangleF rectangle)
{
RectangleF result = Intersect(rectangle, this);
this.X = result.X;
this.Y = result.Y;
this.Width = result.Width;
this.Height = result.Height;
}
/// <summary>
/// Inflates this <see cref="RectangleF"/> by the specified amount.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Inflate(float width, float height)
{
this.X -= width;
this.Y -= height;
this.Width += 2 * width;
this.Height += 2 * height;
}
/// <summary>
/// Inflates this <see cref="RectangleF"/> by the specified amount.
/// </summary>
/// <param name="size">The size.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Inflate(SizeF size) => this.Inflate(size.Width, size.Height);
/// <summary>
/// Determines if the specfied point is contained within the rectangular region defined by
/// this <see cref="RectangleF"/>.
/// </summary>
/// <param name="x">The x-coordinate of the given point.</param>
/// <param name="y">The y-coordinate of the given point.</param>
/// <returns>The <see cref="bool"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(float x, float y) => this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom;
/// <summary>
/// Determines if the specified point is contained within the rectangular region defined by this <see cref="RectangleF"/> .
/// </summary>
/// <param name="point">The point.</param>
/// <returns>The <see cref="bool"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(PointF point) => this.Contains(point.X, point.Y);
/// <summary>
/// Determines if the rectangular region represented by <paramref name="rectangle"/> is entirely contained
/// within the rectangular region represented by this <see cref="RectangleF"/> .
/// </summary>
/// <param name="rectangle">The rectangle.</param>
/// <returns>The <see cref="bool"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(RectangleF rectangle) =>
(this.X <= rectangle.X) && (rectangle.Right <= this.Right) &&
(this.Y <= rectangle.Y) && (rectangle.Bottom <= this.Bottom);
/// <summary>
/// Determines if the specfied <see cref="RectangleF"/> intersects the rectangular region defined by
/// this <see cref="RectangleF"/>.
/// </summary>
/// <param name="rectangle">The other Rectange. </param>
/// <returns>The <see cref="bool"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IntersectsWith(RectangleF rectangle) =>
(rectangle.X < this.Right) && (this.X < rectangle.Right) &&
(rectangle.Y < this.Bottom) && (this.Y < rectangle.Bottom);
/// <summary>
/// Adjusts the location of this rectangle by the specified amount.
/// </summary>
/// <param name="point">The point.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Offset(PointF point) => this.Offset(point.X, point.Y);
/// <summary>
/// Adjusts the location of this rectangle by the specified amount.
/// </summary>
/// <param name="dx">The amount to offset the x-coordinate.</param>
/// <param name="dy">The amount to offset the y-coordinate.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Offset(float dx, float dy)
{
this.X += dx;
this.Y += dy;
}
/// <inheritdoc/>
public override int GetHashCode()
{
return HashCode.Combine(this.X, this.Y, this.Width, this.Height);
}
/// <inheritdoc/>
public override string ToString()
{
return $"RectangleF [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]";
}
/// <inheritdoc/>
public override bool Equals(object obj) => obj is RectangleF other && this.Equals(other);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(RectangleF other) =>
this.X.Equals(other.X) &&
this.Y.Equals(other.Y) &&
this.Width.Equals(other.Width) &&
this.Height.Equals(other.Height);
}
}

2
src/ImageSharp/Primitives/SignedRational.cs

@ -4,7 +4,7 @@
using System;
using System.Globalization;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents a number that can be expressed as a fraction.

296
src/ImageSharp/Primitives/Size.cs

@ -0,0 +1,296 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Stores an ordered pair of integers, which specify a height and width.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public struct Size : IEquatable<Size>
{
/// <summary>
/// Represents a <see cref="Size"/> that has Width and Height values set to zero.
/// </summary>
public static readonly Size Empty = default;
/// <summary>
/// Initializes a new instance of the <see cref="Size"/> struct.
/// </summary>
/// <param name="value">The width and height of the size.</param>
public Size(int value)
: this()
{
this.Width = value;
this.Height = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="Size"/> struct.
/// </summary>
/// <param name="width">The width of the size.</param>
/// <param name="height">The height of the size.</param>
public Size(int width, int height)
{
this.Width = width;
this.Height = height;
}
/// <summary>
/// Initializes a new instance of the <see cref="Size"/> struct.
/// </summary>
/// <param name="size">The size.</param>
public Size(Size size)
: this()
{
this.Width = size.Width;
this.Height = size.Height;
}
/// <summary>
/// Initializes a new instance of the <see cref="Size"/> struct from the given <see cref="Point"/>.
/// </summary>
/// <param name="point">The point.</param>
public Size(Point point)
{
this.Width = point.X;
this.Height = point.Y;
}
/// <summary>
/// Gets or sets the width of this <see cref="Size"/>.
/// </summary>
public int Width { get; set; }
/// <summary>
/// Gets or sets the height of this <see cref="Size"/>.
/// </summary>
public int Height { get; set; }
/// <summary>
/// Gets a value indicating whether this <see cref="Size"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Creates a <see cref="SizeF"/> with the dimensions of the specified <see cref="Size"/>.
/// </summary>
/// <param name="size">The point.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator SizeF(Size size) => new SizeF(size.Width, size.Height);
/// <summary>
/// Converts the given <see cref="Size"/> into a <see cref="Point"/>.
/// </summary>
/// <param name="size">The size.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Point(Size size) => new Point(size.Width, size.Height);
/// <summary>
/// Computes the sum of adding two sizes.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>
/// The <see cref="Size"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Size operator +(Size left, Size right) => Add(left, right);
/// <summary>
/// Computes the difference left by subtracting one size from another.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>
/// The <see cref="Size"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Size operator -(Size left, Size right) => Subtract(left, right);
/// <summary>
/// Multiplies a <see cref="Size"/> by an <see cref="int"/> producing <see cref="Size"/>.
/// </summary>
/// <param name="left">Multiplier of type <see cref="int"/>.</param>
/// <param name="right">Multiplicand of type <see cref="Size"/>.</param>
/// <returns>Product of type <see cref="Size"/>.</returns>
public static Size operator *(int left, Size right) => Multiply(right, left);
/// <summary>
/// Multiplies <see cref="Size"/> by an <see cref="int"/> producing <see cref="Size"/>.
/// </summary>
/// <param name="left">Multiplicand of type <see cref="Size"/>.</param>
/// <param name="right">Multiplier of type <see cref="int"/>.</param>
/// <returns>Product of type <see cref="Size"/>.</returns>
public static Size operator *(Size left, int right) => Multiply(left, right);
/// <summary>
/// Divides <see cref="Size"/> by an <see cref="int"/> producing <see cref="Size"/>.
/// </summary>
/// <param name="left">Dividend of type <see cref="Size"/>.</param>
/// <param name="right">Divisor of type <see cref="int"/>.</param>
/// <returns>Result of type <see cref="Size"/>.</returns>
public static Size operator /(Size left, int right) => new Size(unchecked(left.Width / right), unchecked(left.Height / right));
/// <summary>
/// Multiplies <see cref="Size"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Multiplier of type <see cref="float"/>.</param>
/// <param name="right">Multiplicand of type <see cref="Size"/>.</param>
/// <returns>Product of type <see cref="SizeF"/>.</returns>
public static SizeF operator *(float left, Size right) => Multiply(right, left);
/// <summary>
/// Multiplies <see cref="Size"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Multiplicand of type <see cref="Size"/>.</param>
/// <param name="right">Multiplier of type <see cref="float"/>.</param>
/// <returns>Product of type <see cref="SizeF"/>.</returns>
public static SizeF operator *(Size left, float right) => Multiply(left, right);
/// <summary>
/// Divides <see cref="Size"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Dividend of type <see cref="Size"/>.</param>
/// <param name="right">Divisor of type <see cref="int"/>.</param>
/// <returns>Result of type <see cref="SizeF"/>.</returns>
public static SizeF operator /(Size left, float right)
=> new SizeF(left.Width / right, left.Height / right);
/// <summary>
/// Compares two <see cref="Size"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="Size"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="Size"/> on the right side of the operand.
/// </param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Size left, Size right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Size"/> objects for inequality.
/// </summary>
/// <param name="left">
/// The <see cref="Size"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="Size"/> on the right side of the operand.
/// </param>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Size left, Size right) => !left.Equals(right);
/// <summary>
/// Performs vector addition of two <see cref="Size"/> objects.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>The <see cref="Size"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Size Add(Size left, Size right) => new Size(unchecked(left.Width + right.Width), unchecked(left.Height + right.Height));
/// <summary>
/// Contracts a <see cref="Size"/> by another <see cref="Size"/>.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>The <see cref="Size"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Size Subtract(Size left, Size right) => new Size(unchecked(left.Width - right.Width), unchecked(left.Height - right.Height));
/// <summary>
/// Converts a <see cref="SizeF"/> to a <see cref="Size"/> by performing a ceiling operation on all the dimensions.
/// </summary>
/// <param name="size">The size.</param>
/// <returns>The <see cref="Size"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Size Ceiling(SizeF size) => new Size(unchecked((int)MathF.Ceiling(size.Width)), unchecked((int)MathF.Ceiling(size.Height)));
/// <summary>
/// Converts a <see cref="SizeF"/> to a <see cref="Size"/> by performing a round operation on all the dimensions.
/// </summary>
/// <param name="size">The size.</param>
/// <returns>The <see cref="Size"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Size Round(SizeF size) => new Size(unchecked((int)MathF.Round(size.Width)), unchecked((int)MathF.Round(size.Height)));
/// <summary>
/// Transforms a size by the given matrix.
/// </summary>
/// <param name="size">The source size.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>A transformed size.</returns>
public static SizeF Transform(Size size, Matrix3x2 matrix)
{
var v = Vector2.Transform(new Vector2(size.Width, size.Height), matrix);
return new SizeF(v.X, v.Y);
}
/// <summary>
/// Converts a <see cref="SizeF"/> to a <see cref="Size"/> by performing a round operation on all the dimensions.
/// </summary>
/// <param name="size">The size.</param>
/// <returns>The <see cref="Size"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Size Truncate(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height));
/// <summary>
/// Deconstructs this size into two integers.
/// </summary>
/// <param name="width">The out value for the width.</param>
/// <param name="height">The out value for the height.</param>
public void Deconstruct(out int width, out int height)
{
width = this.Width;
height = this.Height;
}
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.Width, this.Height);
/// <inheritdoc/>
public override string ToString() => $"Size [ Width={this.Width}, Height={this.Height} ]";
/// <inheritdoc/>
public override bool Equals(object obj) => obj is Size other && this.Equals(other);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Size other) => this.Width.Equals(other.Width) && this.Height.Equals(other.Height);
/// <summary>
/// Multiplies <see cref="Size"/> by an <see cref="int"/> producing <see cref="Size"/>.
/// </summary>
/// <param name="size">Multiplicand of type <see cref="Size"/>.</param>
/// <param name="multiplier">Multiplier of type <see cref="int"/>.</param>
/// <returns>Product of type <see cref="Size"/>.</returns>
private static Size Multiply(Size size, int multiplier) =>
new Size(unchecked(size.Width * multiplier), unchecked(size.Height * multiplier));
/// <summary>
/// Multiplies <see cref="Size"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="size">Multiplicand of type <see cref="Size"/>.</param>
/// <param name="multiplier">Multiplier of type <see cref="float"/>.</param>
/// <returns>Product of type SizeF.</returns>
private static SizeF Multiply(Size size, float multiplier) =>
new SizeF(size.Width * multiplier, size.Height * multiplier);
}
}

233
src/ImageSharp/Primitives/SizeF.cs

@ -0,0 +1,233 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Stores an ordered pair of single precision floating points, which specify a height and width.
/// </summary>
/// <remarks>
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
public struct SizeF : IEquatable<SizeF>
{
/// <summary>
/// Represents a <see cref="SizeF"/> that has Width and Height values set to zero.
/// </summary>
public static readonly SizeF Empty = default;
/// <summary>
/// Initializes a new instance of the <see cref="SizeF"/> struct.
/// </summary>
/// <param name="width">The width of the size.</param>
/// <param name="height">The height of the size.</param>
public SizeF(float width, float height)
{
this.Width = width;
this.Height = height;
}
/// <summary>
/// Initializes a new instance of the <see cref="SizeF"/> struct.
/// </summary>
/// <param name="size">The size.</param>
public SizeF(SizeF size)
: this()
{
this.Width = size.Width;
this.Height = size.Height;
}
/// <summary>
/// Initializes a new instance of the <see cref="SizeF"/> struct from the given <see cref="PointF"/>.
/// </summary>
/// <param name="point">The point.</param>
public SizeF(PointF point)
{
this.Width = point.X;
this.Height = point.Y;
}
/// <summary>
/// Gets or sets the width of this <see cref="SizeF"/>.
/// </summary>
public float Width { get; set; }
/// <summary>
/// Gets or sets the height of this <see cref="SizeF"/>.
/// </summary>
public float Height { get; set; }
/// <summary>
/// Gets a value indicating whether this <see cref="SizeF"/> is empty.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public bool IsEmpty => this.Equals(Empty);
/// <summary>
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
/// </summary>
/// <param name="point">The point.</param>
/// <returns>
/// The <see cref="Vector2"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Vector2(SizeF point) => new Vector2(point.Width, point.Height);
/// <summary>
/// Creates a <see cref="Size"/> with the dimensions of the specified <see cref="SizeF"/> by truncating each of the dimensions.
/// </summary>
/// <param name="size">The size.</param>
/// <returns>
/// The <see cref="Size"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator Size(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height));
/// <summary>
/// Converts the given <see cref="SizeF"/> into a <see cref="PointF"/>.
/// </summary>
/// <param name="size">The size.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator PointF(SizeF size) => new PointF(size.Width, size.Height);
/// <summary>
/// Computes the sum of adding two sizes.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>
/// The <see cref="SizeF"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SizeF operator +(SizeF left, SizeF right) => Add(left, right);
/// <summary>
/// Computes the difference left by subtracting one size from another.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>
/// The <see cref="SizeF"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SizeF operator -(SizeF left, SizeF right) => Subtract(left, right);
/// <summary>
/// Multiplies <see cref="SizeF"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Multiplier of type <see cref="float"/>.</param>
/// <param name="right">Multiplicand of type <see cref="SizeF"/>.</param>
/// <returns>Product of type <see cref="SizeF"/>.</returns>
public static SizeF operator *(float left, SizeF right) => Multiply(right, left);
/// <summary>
/// Multiplies <see cref="SizeF"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Multiplicand of type <see cref="SizeF"/>.</param>
/// <param name="right">Multiplier of type <see cref="float"/>.</param>
/// <returns>Product of type <see cref="SizeF"/>.</returns>
public static SizeF operator *(SizeF left, float right) => Multiply(left, right);
/// <summary>
/// Divides <see cref="SizeF"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="left">Dividend of type <see cref="SizeF"/>.</param>
/// <param name="right">Divisor of type <see cref="int"/>.</param>
/// <returns>Result of type <see cref="SizeF"/>.</returns>
public static SizeF operator /(SizeF left, float right)
=> new SizeF(left.Width / right, left.Height / right);
/// <summary>
/// Compares two <see cref="SizeF"/> objects for equality.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(SizeF left, SizeF right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="SizeF"/> objects for inequality.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(SizeF left, SizeF right) => !left.Equals(right);
/// <summary>
/// Performs vector addition of two <see cref="SizeF"/> objects.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>The <see cref="SizeF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SizeF Add(SizeF left, SizeF right) => new SizeF(left.Width + right.Width, left.Height + right.Height);
/// <summary>
/// Contracts a <see cref="SizeF"/> by another <see cref="SizeF"/>.
/// </summary>
/// <param name="left">The size on the left hand of the operand.</param>
/// <param name="right">The size on the right hand of the operand.</param>
/// <returns>The <see cref="SizeF"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SizeF Subtract(SizeF left, SizeF right) => new SizeF(left.Width - right.Width, left.Height - right.Height);
/// <summary>
/// Transforms a size by the given matrix.
/// </summary>
/// <param name="size">The source size.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>A transformed size.</returns>
public static SizeF Transform(SizeF size, Matrix3x2 matrix)
{
var v = Vector2.Transform(new Vector2(size.Width, size.Height), matrix);
return new SizeF(v.X, v.Y);
}
/// <summary>
/// Deconstructs this size into two floats.
/// </summary>
/// <param name="width">The out value for the width.</param>
/// <param name="height">The out value for the height.</param>
public void Deconstruct(out float width, out float height)
{
width = this.Width;
height = this.Height;
}
/// <inheritdoc/>
public override int GetHashCode() => HashCode.Combine(this.Width, this.Height);
/// <inheritdoc/>
public override string ToString() => $"SizeF [ Width={this.Width}, Height={this.Height} ]";
/// <inheritdoc/>
public override bool Equals(object obj) => obj is SizeF && this.Equals((SizeF)obj);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(SizeF other) => this.Width.Equals(other.Width) && this.Height.Equals(other.Height);
/// <summary>
/// Multiplies <see cref="SizeF"/> by a <see cref="float"/> producing <see cref="SizeF"/>.
/// </summary>
/// <param name="size">Multiplicand of type <see cref="SizeF"/>.</param>
/// <param name="multiplier">Multiplier of type <see cref="float"/>.</param>
/// <returns>Product of type SizeF.</returns>
private static SizeF Multiply(SizeF size, float multiplier) =>
new SizeF(size.Width * multiplier, size.Height * multiplier);
}
}

3
src/ImageSharp/Primitives/ValueSize.cs

@ -2,9 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Primitives
namespace SixLabors.ImageSharp
{
/// <summary>
/// Represents a value in relation to a value on the image.

1
src/ImageSharp/Processing/AffineTransformBuilder.cs

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Numerics;
using SixLabors.ImageSharp.Processing.Processors.Transforms;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing
{

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

Loading…
Cancel
Save