Browse Source

Merge branch 'master' into master

af/merge-core
Vicente Penades 8 years ago
committed by GitHub
parent
commit
6ccddee174
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/ImageSharp.Drawing/ImageSharp.Drawing.csproj
  2. 2
      src/ImageSharp.Drawing/Primitives/ShapeRegion.cs
  3. 1
      src/ImageSharp.Drawing/Processing/BrushApplicator.cs
  4. 1
      src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs
  5. 1
      src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs
  6. 5
      src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
  7. 9
      src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
  8. 1
      src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs
  9. 1
      src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs
  10. 1
      src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs
  11. 1
      src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs
  12. 2
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  13. 1
      src/ImageSharp/Advanced/IPixelSource.cs
  14. 22
      src/ImageSharp/Common/Extensions/ConfigurationExtensions.cs
  15. 13
      src/ImageSharp/Common/Extensions/StreamExtensions.cs
  16. 6
      src/ImageSharp/Common/Helpers/ParallelFor.cs
  17. 21
      src/ImageSharp/Configuration.cs
  18. 1
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  19. 1
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  20. 1
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  21. 2
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  22. 2
      src/ImageSharp/Formats/Gif/LzwDecoder.cs
  23. 2
      src/ImageSharp/Formats/Gif/LzwEncoder.cs
  24. 1
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.CopyTo.cs
  25. 1
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs
  26. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs
  27. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs
  28. 1
      src/ImageSharp/Formats/Jpeg/Components/Decoder/IJpegComponent.cs
  29. 1
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs
  30. 1
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponent.cs
  31. 1
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs
  32. 1
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
  33. 1
      src/ImageSharp/Formats/Jpeg/Components/GenericBlock8x8.cs
  34. 1
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  35. 1
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  36. 1
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  37. 1
      src/ImageSharp/Image.Decode.cs
  38. 1
      src/ImageSharp/Image.WrapMemory.cs
  39. 1
      src/ImageSharp/ImageExtensions.Internal.cs
  40. 1
      src/ImageSharp/ImageFrameCollection.cs
  41. 3
      src/ImageSharp/ImageFrame{TPixel}.cs
  42. 12
      src/ImageSharp/ImageSharp.csproj
  43. 1
      src/ImageSharp/Image{TPixel}.cs
  44. 21
      src/ImageSharp/Memory/AllocationOptions.cs
  45. 82
      src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs
  46. 71
      src/ImageSharp/Memory/ArrayPoolMemoryAllocator.CommonFactoryMethods.cs
  47. 140
      src/ImageSharp/Memory/ArrayPoolMemoryAllocator.cs
  48. 59
      src/ImageSharp/Memory/BasicArrayBuffer.cs
  49. 13
      src/ImageSharp/Memory/BasicByteBuffer.cs
  50. 3
      src/ImageSharp/Memory/Buffer2DExtensions.cs
  51. 6
      src/ImageSharp/Memory/Buffer2D{T}.cs
  52. 7
      src/ImageSharp/Memory/BufferArea{T}.cs
  53. 18
      src/ImageSharp/Memory/IManagedByteBuffer.cs
  54. 43
      src/ImageSharp/Memory/ManagedBufferBase.cs
  55. 39
      src/ImageSharp/Memory/MemoryAllocator.cs
  56. 8
      src/ImageSharp/Memory/MemoryAllocatorExtensions.cs
  57. 18
      src/ImageSharp/Memory/MemoryOwnerExtensions.cs
  58. 4
      src/ImageSharp/Memory/MemorySource.cs
  59. 21
      src/ImageSharp/Memory/SimpleGcMemoryAllocator.cs
  60. 2
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
  61. 30
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
  62. 5
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
  63. 16
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
  64. 5
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs
  65. 6
      src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs
  66. 5
      src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs
  67. 2
      src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs
  68. 4
      src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs
  69. 1
      src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs
  70. 5
      src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs
  71. 31
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  72. 39
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  73. 1
      src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs
  74. 1
      src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs
  75. 9
      src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
  76. 4
      src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
  77. 9
      src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs
  78. 9
      src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
  79. 9
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  80. 12
      src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
  81. 2
      src/ImageSharp/Processing/Processors/Transforms/WeightsBuffer.cs
  82. 2
      src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs
  83. 62
      tests/ImageSharp.Benchmarks/Codecs/CopyPixels.cs
  84. 2
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave.cs
  85. 17
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs
  86. 5
      tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs
  87. 5
      tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs
  88. 5
      tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs
  89. 5
      tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs
  90. 7
      tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs
  91. 2
      tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
  92. 40
      tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs
  93. 74
      tests/ImageSharp.Benchmarks/Samplers/Glow.cs
  94. 2
      tests/ImageSharp.Benchmarks/Samplers/Resize.cs
  95. 25
      tests/ImageSharp.Tests/ConfigurationTests.cs
  96. 3
      tests/ImageSharp.Tests/Drawing/BeziersTests.cs
  97. 4
      tests/ImageSharp.Tests/Drawing/DrawPathTests.cs
  98. 4
      tests/ImageSharp.Tests/Drawing/FillPatternTests.cs
  99. 4
      tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs
  100. 3
      tests/ImageSharp.Tests/Drawing/LineTests.cs

5
src/ImageSharp.Drawing/ImageSharp.Drawing.csproj

@ -37,10 +37,9 @@
<ProjectReference Include="..\ImageSharp\ImageSharp.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SixLabors.Core" Version="1.0.0-beta0005" />
<AdditionalFiles Include="..\..\stylecop.json" />
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-dev000087" />
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-dev000079" />
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta0007" />
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0007" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta007">
<PrivateAssets>All</PrivateAssets>
</PackageReference>

2
src/ImageSharp.Drawing/Primitives/ShapeRegion.cs

@ -3,6 +3,8 @@
using System;
using System.Buffers;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
using SixLabors.Primitives;
using SixLabors.Shapes;

1
src/ImageSharp.Drawing/Processing/BrushApplicator.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

1
src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs

@ -4,6 +4,7 @@
using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;

1
src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;

5
src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -139,10 +140,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
amount.GetSpan().Fill(this.Opacity);
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> background = source.GetPixelRowSpan(y).Slice(minX, width);

9
src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -54,10 +55,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
// If there's no reason for blending, then avoid it.
if (this.IsSolidBrushWithoutBlending(out SolidBrush<TPixel> solidBrush))
{
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
source.GetPixelRowSpan(y).Slice(minX, width).Fill(solidBrush.Color);
@ -84,10 +85,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
{
amount.GetSpan().Fill(1f);
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
int offsetY = y - startY;

1
src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs

@ -4,6 +4,7 @@
using System;
using System.Buffers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Utils;

1
src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs

@ -6,6 +6,7 @@ using System.Buffers;
using System.Collections.Generic;
using SixLabors.Fonts;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Utils;
using SixLabors.Memory;

1
src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;

1
src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;

2
src/ImageSharp/Advanced/AdvancedImageExtensions.cs

@ -3,6 +3,8 @@
using System;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

1
src/ImageSharp/Advanced/IPixelSource.cs

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

22
src/ImageSharp/Common/Extensions/ConfigurationExtensions.cs

@ -0,0 +1,22 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Threading.Tasks;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Contains extension methods for <see cref="Configuration"/>
/// </summary>
internal static class ConfigurationExtensions
{
/// <summary>
/// Creates a <see cref="ParallelOptions"/> object based on <paramref name="configuration"/>,
/// having <see cref="ParallelOptions.MaxDegreeOfParallelism"/> set to <see cref="Configuration.MaxDegreeOfParallelism"/>
/// </summary>
public static ParallelOptions GetParallelOptions(this Configuration configuration)
{
return new ParallelOptions() { MaxDegreeOfParallelism = configuration.MaxDegreeOfParallelism };
}
}
}

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

@ -4,6 +4,9 @@
using System;
using System.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp
{
/// <summary>
@ -69,5 +72,15 @@ namespace SixLabors.ImageSharp
}
}
}
public static void Read(this Stream stream, IManagedByteBuffer buffer)
{
stream.Read(buffer.Array, 0, buffer.Length());
}
public static void Write(this Stream stream, IManagedByteBuffer buffer)
{
stream.Write(buffer.Array, 0, buffer.Length());
}
}
}

6
src/ImageSharp/Common/Helpers/ParallelFor.cs

@ -11,11 +11,11 @@ namespace SixLabors.ImageSharp
internal static class ParallelFor
{
/// <summary>
/// Helper method to execute Parallel.For using the settings in <see cref="Configuration.ParallelOptions"/>
/// Helper method to execute Parallel.For using the settings in <paramref name="configuration"/>
/// </summary>
public static void WithConfiguration(int fromInclusive, int toExclusive, Configuration configuration, Action<int> body)
{
Parallel.For(fromInclusive, toExclusive, configuration.ParallelOptions, body);
Parallel.For(fromInclusive, toExclusive, configuration.GetParallelOptions(), body);
}
/// <summary>
@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp
where T : struct
{
MemoryAllocator memoryAllocator = configuration.MemoryAllocator;
ParallelOptions parallelOptions = configuration.ParallelOptions;
ParallelOptions parallelOptions = configuration.GetParallelOptions();
IMemoryOwner<T> InitBuffer()
{

21
src/ImageSharp/Configuration.cs

@ -27,6 +27,8 @@ namespace SixLabors.ImageSharp
/// </summary>
private static readonly Lazy<Configuration> Lazy = new Lazy<Configuration>(CreateDefaultInstance);
private int maxDegreeOfParallelism = Environment.ProcessorCount;
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
@ -55,9 +57,22 @@ namespace SixLabors.ImageSharp
public static Configuration Default { get; } = Lazy.Value;
/// <summary>
/// Gets the global parallel options for processing tasks in parallel.
/// Gets or sets the maximum number of concurrent tasks enabled in ImageSharp algorithms
/// configured with this <see cref="Configuration"/> instance.
/// </summary>
public ParallelOptions ParallelOptions { get; private set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
public int MaxDegreeOfParallelism
{
get => this.maxDegreeOfParallelism;
set
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException(nameof(this.MaxDegreeOfParallelism));
}
this.maxDegreeOfParallelism = value;
}
}
/// <summary>
/// Gets the currently registered <see cref="IImageFormat"/>s.
@ -114,7 +129,7 @@ namespace SixLabors.ImageSharp
{
return new Configuration
{
ParallelOptions = this.ParallelOptions,
MaxDegreeOfParallelism = this.MaxDegreeOfParallelism,
ImageFormatsManager = this.ImageFormatsManager,
MemoryAllocator = this.MemoryAllocator,
ImageOperationsProvider = this.ImageOperationsProvider,

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

@ -6,6 +6,7 @@ using System.Buffers.Binary;
using System.IO;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

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

@ -4,6 +4,7 @@
using System;
using System.IO;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

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

@ -7,6 +7,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

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

@ -7,6 +7,8 @@ using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;

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

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

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

@ -6,6 +6,8 @@ using System.Buffers;
using System.IO;
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/Block8x8F.CopyTo.cs

@ -4,6 +4,7 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
// ReSharper disable InconsistentNaming

1
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs

@ -7,6 +7,7 @@ using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.Common.Tuples;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters

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

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

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

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

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

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

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

@ -3,6 +3,7 @@
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
using SixLabors.Primitives;

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

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

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

@ -3,6 +3,7 @@
using System;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
using SixLabors.Primitives;

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

@ -6,6 +6,7 @@ using System.Buffers;
using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;

1
src/ImageSharp/Formats/Jpeg/Components/GenericBlock8x8.cs

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

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

@ -12,6 +12,7 @@ using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.MetaData.Profiles.Icc;

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

@ -13,6 +13,7 @@ using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Png.Filters;
using SixLabors.ImageSharp.Formats.Png.Zlib;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;

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

@ -9,6 +9,7 @@ using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Png.Filters;
using SixLabors.ImageSharp.Formats.Png.Zlib;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Quantization;

1
src/ImageSharp/Image.Decode.cs

@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

1
src/ImageSharp/Image.WrapMemory.cs

@ -4,6 +4,7 @@
using System;
using System.Buffers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

1
src/ImageSharp/ImageExtensions.Internal.cs

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

1
src/ImageSharp/ImageFrameCollection.cs

@ -5,6 +5,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

3
src/ImageSharp/ImageFrame{TPixel}.cs

@ -7,6 +7,7 @@ using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@ -89,7 +90,7 @@ namespace SixLabors.ImageSharp
this.MemoryAllocator = configuration.MemoryAllocator;
this.PixelBuffer = this.MemoryAllocator.Allocate2D<TPixel>(width, height);
this.MetaData = metaData;
this.Clear(configuration.ParallelOptions, backgroundColor);
this.Clear(configuration.GetParallelOptions(), backgroundColor);
}
/// <summary>

12
src/ImageSharp/ImageSharp.csproj

@ -35,21 +35,13 @@
<Compile Include="..\Shared\*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SixLabors.Core" Version="1.0.0-beta0005" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.1" />
<PackageReference Include="SixLabors.Core" Version="1.0.0-beta0006" />
<AdditionalFiles Include="..\..\stylecop.json" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.0-beta007">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'netcoreapp2.1'">
<PackageReference Include="System.Buffers" Version="4.5.0" />
<PackageReference Include="System.Memory" Version="4.5.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.IO.UnmanagedMemoryStream" Version="4.3.0" />

1
src/ImageSharp/Image{TPixel}.cs

@ -8,6 +8,7 @@ using System.Linq;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

21
src/ImageSharp/Memory/AllocationOptions.cs

@ -1,21 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.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
}
}

82
src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs

@ -1,82 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Runtime.InteropServices;
namespace SixLabors.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 />
protected override void Dispose(bool disposing)
{
if (!disposing || this.Data == null || this.sourcePoolReference == null)
{
return;
}
if (this.sourcePoolReference.TryGetTarget(out ArrayPool<byte> pool))
{
pool.Return(this.Data);
}
this.sourcePoolReference = null;
this.Data = null;
}
public override Span<T> GetSpan() => MemoryMarshal.Cast<byte, T>(this.Data.AsSpan()).Slice(0, this.length);
protected override object GetPinnableObject() => this.Data;
}
/// <summary>
/// The <see cref="IManagedByteBuffer"/> implementation of <see cref="ArrayPoolMemoryAllocator"/>.
/// </summary>
private class ManagedByteBuffer : Buffer<byte>, IManagedByteBuffer
{
public ManagedByteBuffer(byte[] data, int length, ArrayPool<byte> sourcePool)
: base(data, length, sourcePool)
{
}
public byte[] Array => this.Data;
}
}
}

71
src/ImageSharp/Memory/ArrayPoolMemoryAllocator.CommonFactoryMethods.cs

@ -1,71 +0,0 @@
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.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 <see cref="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 limited memory capabilities. Only small images are pooled, which can result in reduced througput.
/// </summary>
/// <returns>The memory manager</returns>
public static ArrayPoolMemoryAllocator CreateWithModeratePooling()
{
return new ArrayPoolMemoryAllocator(1024 * 1024, 32 * 1024, 16, 24);
}
/// <summary>
/// Only pool small buffers like image rows.
/// </summary>
/// <returns>The memory manager</returns>
public static ArrayPoolMemoryAllocator CreateWithMinimalPooling()
{
return new ArrayPoolMemoryAllocator(64 * 1024, 32 * 1024, 8, 24);
}
/// <summary>
/// RAM is not an issue for me, gimme maximum througput!
/// </summary>
/// <returns>The memory manager</returns>
public static ArrayPoolMemoryAllocator CreateWithAggressivePooling()
{
return new ArrayPoolMemoryAllocator(128 * 1024 * 1024, 32 * 1024 * 1024, 16, 32);
}
}
}

140
src/ImageSharp/Memory/ArrayPoolMemoryAllocator.cs

@ -1,140 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
using System.Runtime.CompilerServices;
namespace SixLabors.Memory
{
/// <summary>
/// Implements <see cref="MemoryAllocator"/> by allocating memory from <see cref="ArrayPool{T}"/>.
/// </summary>
public sealed partial class ArrayPoolMemoryAllocator : MemoryAllocator
{
/// <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;
private readonly int maxArraysPerBucketNormalPool;
private readonly int maxArraysPerBucketLargePool;
/// <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)
{
ImageSharp.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 />
internal override IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
{
int itemSizeBytes = Unsafe.SizeOf<T>();
int bufferSizeInBytes = length * itemSizeBytes;
ArrayPool<byte> pool = this.GetArrayPool(bufferSizeInBytes);
byte[] byteArray = pool.Rent(bufferSizeInBytes);
var buffer = new Buffer<T>(byteArray, length, pool);
if (options == AllocationOptions.Clean)
{
buffer.Clear();
}
return buffer;
}
/// <inheritdoc />
internal override IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options)
{
ArrayPool<byte> pool = this.GetArrayPool(length);
byte[] byteArray = pool.Rent(length);
var buffer = new ManagedByteBuffer(byteArray, length, pool);
if (options == AllocationOptions.Clean)
{
buffer.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);
}
}
}

59
src/ImageSharp/Memory/BasicArrayBuffer.cs

@ -1,59 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.Memory
{
/// <summary>
/// Wraps an array as an <see cref="IManagedByteBuffer"/> instance.
/// </summary>
internal class BasicArrayBuffer<T> : ManagedBufferBase<T>
where T : struct
{
public BasicArrayBuffer(T[] array, int length)
{
ImageSharp.DebugGuard.MustBeLessThanOrEqualTo(length, array.Length, nameof(length));
this.Array = array;
this.Length = length;
}
public BasicArrayBuffer(T[] array)
: this(array, array.Length)
{
}
public T[] Array { get; }
public int Length { get; }
/// <summary>
/// Returns a reference to specified element of the buffer.
/// </summary>
/// <param name="index">The index</param>
/// <returns>The reference to the specified element</returns>
public ref T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
DebugGuard.MustBeLessThan(index, this.Length, nameof(index));
Span<T> span = this.GetSpan();
return ref span[index];
}
}
protected override void Dispose(bool disposing)
{
}
public override Span<T> GetSpan() => this.Array.AsSpan(0, this.Length);
protected override object GetPinnableObject()
{
return this.Array;
}
}
}

13
src/ImageSharp/Memory/BasicByteBuffer.cs

@ -1,13 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.Memory
{
internal sealed class BasicByteBuffer : BasicArrayBuffer<byte>, IManagedByteBuffer
{
internal BasicByteBuffer(byte[] array)
: base(array)
{
}
}
}

3
src/ImageSharp/Memory/Buffer2DExtensions.cs

@ -3,9 +3,10 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
namespace SixLabors.Memory
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Defines extension methods for <see cref="Buffer2D{T}"/>.

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

@ -2,11 +2,11 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
namespace SixLabors.Memory
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Represents a buffer of value type objects
@ -62,7 +62,7 @@ namespace SixLabors.Memory
get
{
ImageSharp.DebugGuard.MustBeLessThan(x, this.Width, nameof(x));
DebugGuard.MustBeLessThan(y, this.Height, nameof(y));
ImageSharp.DebugGuard.MustBeLessThan(y, this.Height, nameof(y));
Span<T> span = this.Span;
return ref span[(this.Width * y) + x];
}

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

@ -1,8 +1,11 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
namespace SixLabors.Memory
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Represents a rectangular area inside a 2D memory buffer (<see cref="Buffer2D{T}"/>).
@ -120,7 +123,7 @@ namespace SixLabors.Memory
public BufferArea<T> GetSubArea(Rectangle rectangle)
{
ImageSharp.DebugGuard.MustBeLessThanOrEqualTo(rectangle.Width, this.Rectangle.Width, nameof(rectangle));
DebugGuard.MustBeLessThanOrEqualTo(rectangle.Height, this.Rectangle.Height, nameof(rectangle));
ImageSharp.DebugGuard.MustBeLessThanOrEqualTo(rectangle.Height, this.Rectangle.Height, nameof(rectangle));
int x = this.Rectangle.X + rectangle.X;
int y = this.Rectangle.Y + rectangle.Y;

18
src/ImageSharp/Memory/IManagedByteBuffer.cs

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

43
src/ImageSharp/Memory/ManagedBufferBase.cs

@ -1,43 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
using System.Runtime.InteropServices;
namespace SixLabors.Memory
{
/// <summary>
/// Provides a base class for <see cref="IMemoryOwner{T}"/> implementations by implementing pinning logic for <see cref="MemoryManager{T}"/> adaption.
/// </summary>
internal abstract class ManagedBufferBase<T> : MemoryManager<T>
where T : struct
{
private GCHandle pinHandle;
public bool IsMemoryOwner => true;
/// <summary>
/// Gets the object that should be pinned.
/// </summary>
protected abstract object GetPinnableObject();
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);
}
public override void Unpin()
{
if (this.pinHandle.IsAllocated)
{
this.pinHandle.Free();
}
}
}
}

39
src/ImageSharp/Memory/MemoryAllocator.cs

@ -1,39 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
namespace SixLabors.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>
internal 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>
internal 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()
{
}
}
}

8
src/ImageSharp/Memory/MemoryAllocatorExtensions.cs

@ -1,8 +1,12 @@
using System.Buffers;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
using SixLabors.Memory;
using SixLabors.Primitives;
namespace SixLabors.Memory
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Extension methods for <see cref="MemoryAllocator"/>.

18
src/ImageSharp/Memory/BufferExtensions.cs → src/ImageSharp/Memory/MemoryOwnerExtensions.cs

@ -3,13 +3,15 @@
using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.Memory
namespace SixLabors.ImageSharp.Memory
{
internal static class BufferExtensions
/// <summary>
/// Extension methods for <see cref="IMemoryOwner{T}"/>
/// </summary>
internal static class MemoryOwnerExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> GetSpan<T>(this IMemoryOwner<T> buffer)
@ -57,15 +59,5 @@ namespace SixLabors.Memory
public static ref T GetReference<T>(this IMemoryOwner<T> buffer)
where T : struct =>
ref MemoryMarshal.GetReference(buffer.GetSpan());
public static void Read(this Stream stream, IManagedByteBuffer buffer)
{
stream.Read(buffer.Array, 0, buffer.Length());
}
public static void Write(this Stream stream, IManagedByteBuffer buffer)
{
stream.Write(buffer.Array, 0, buffer.Length());
}
}
}

4
src/ImageSharp/Memory/MemorySource.cs

@ -4,7 +4,9 @@
using System;
using System.Buffers;
namespace SixLabors.Memory
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Memory
{
/// <summary>
/// Holds a <see cref="System.Memory{T}"/> that is either OWNED or CONSUMED.

21
src/ImageSharp/Memory/SimpleGcMemoryAllocator.cs

@ -1,21 +0,0 @@
using System.Buffers;
namespace SixLabors.Memory
{
/// <summary>
/// Implements <see cref="MemoryAllocator"/> by newing up arrays by the GC on every allocation requests.
/// </summary>
public sealed class SimpleGcMemoryAllocator : MemoryAllocator
{
/// <inheritdoc />
internal override IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
{
return new BasicArrayBuffer<T>(new T[length]);
}
internal override IManagedByteBuffer AllocateManagedByteBuffer(int length, AllocationOptions options)
{
return new BasicByteBuffer(new byte[length]);
}
}
}

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

@ -5,6 +5,8 @@
using System;
using System.Numerics;
using System.Buffers;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders

30
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs

@ -70,25 +70,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
Parallel.For(
ParallelFor.WithConfiguration(
startY,
endY,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y);
Rgba32 rgba = default;
for (int x = startX; x < endX; x++)
{
ref TPixel color = ref row[x];
color.ToRgba32(ref rgba);
Span<TPixel> row = source.GetPixelRowSpan(y);
Rgba32 rgba = default;
for (int x = startX; x < endX; x++)
{
ref TPixel color = ref row[x];
color.ToRgba32(ref rgba);
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
color = luminance >= threshold ? upper : lower;
}
});
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly
? rgba.A
: (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
color = luminance >= threshold ? upper : lower;
}
});
}
}
}

5
src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;
@ -61,10 +62,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
source.CopyTo(targetPixels);
Parallel.For(
ParallelFor.WithConfiguration(
startY,
endY,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

16
src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs

@ -4,6 +4,8 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing.Processors;
@ -43,12 +45,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
ParallelOptions parallelOptions = configuration.ParallelOptions;
using (Buffer2D<TPixel> firstPassPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size()))
{
this.ApplyConvolution(firstPassPixels, source.PixelBuffer, source.Bounds(), this.KernelX, parallelOptions);
this.ApplyConvolution(source.PixelBuffer, firstPassPixels, sourceRectangle, this.KernelY, parallelOptions);
this.ApplyConvolution(firstPassPixels, source.PixelBuffer, source.Bounds(), this.KernelX, configuration);
this.ApplyConvolution(source.PixelBuffer, firstPassPixels, sourceRectangle, this.KernelY, configuration);
}
}
@ -62,13 +62,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="kernel">The kernel operator.</param>
/// <param name="parallelOptions">The parallel options</param>
/// <param name="configuration">The <see cref="Configuration"/></param>
private void ApplyConvolution(
Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels,
Rectangle sourceRectangle,
DenseMatrix<float> kernel,
ParallelOptions parallelOptions)
Configuration configuration)
{
int kernelHeight = kernel.Rows;
int kernelWidth = kernel.Columns;
@ -82,10 +82,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
int maxY = endY - 1;
int maxX = endX - 1;
Parallel.For(
ParallelFor.WithConfiguration(
startY,
endY,
parallelOptions,
configuration,
y =>
{
Span<TPixel> targetRow = targetPixels.GetRowSpan(y);

5
src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing.Processors;
@ -51,10 +52,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
{
source.CopyTo(targetPixels);
Parallel.For(
ParallelFor.WithConfiguration(
startY,
endY,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

6
src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor.cs

@ -6,6 +6,8 @@ using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing.Processors.Filters;
@ -133,10 +135,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
Buffer2D<TPixel> passPixels = pass.PixelBuffer;
Buffer2D<TPixel> targetPixels = source.PixelBuffer;
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
int offsetY = y - shiftY;

5
src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -69,10 +70,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
{
source.CopyTo(targetPixels);
Parallel.For(
ParallelFor.WithConfiguration(
startY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

2
src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs

@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
Parallel.ForEach(
range,
configuration.ParallelOptions,
configuration.GetParallelOptions(),
y =>
{
int offsetY = y - startY;

4
src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs

@ -41,10 +41,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
int endX = interest.Right;
Matrix4x4 matrix = this.Matrix;
Parallel.For(
ParallelFor.WithConfiguration(
startY,
endY,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y);

1
src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs

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

5
src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -81,10 +82,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.GraphicsOptions.BlenderMode);
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> destination = source.GetPixelRowSpan(y - startY).Slice(minX - startX, width);

31
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs

@ -6,6 +6,7 @@ using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;
@ -122,27 +123,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
rowColorsSpan[i] = glowColor;
}
Parallel.For(
ParallelFor.WithTemporaryBuffer<float>(
minY,
maxY,
configuration.ParallelOptions,
y =>
configuration,
width,
(y, amounts) =>
{
using (IMemoryOwner<float> amounts = source.MemoryAllocator.Allocate<float>(width))
Span<float> amountsSpan = amounts.GetSpan();
int offsetY = y - startY;
int offsetX = minX - startX;
for (int i = 0; i < width; i++)
{
Span<float> amountsSpan = amounts.GetSpan();
int offsetY = y - startY;
int offsetX = minX - startX;
for (int i = 0; i < width; i++)
{
float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY));
amountsSpan[i] = (this.GraphicsOptions.BlendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(source.MemoryAllocator, destination, destination, rowColors.GetSpan(), amountsSpan);
float distance = Vector2.Distance(center, new Vector2(i + offsetX, offsetY));
amountsSpan[i] = (this.GraphicsOptions.BlendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(source.MemoryAllocator, destination, destination, rowColors.GetSpan(), amountsSpan);
});
}
}

39
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs

@ -6,6 +6,7 @@ using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.Memory;
@ -124,27 +125,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
rowColorsSpan[i] = vignetteColor;
}
Parallel.For(
ParallelFor.WithTemporaryBuffer<float>(
minY,
maxY,
configuration.ParallelOptions,
y =>
configuration,
width,
(y, amounts) =>
{
using (IMemoryOwner<float> amounts = source.MemoryAllocator.Allocate<float>(width))
Span<float> amountsSpan = amounts.GetSpan();
int offsetY = y - startY;
int offsetX = minX - startX;
for (int i = 0; i < width; i++)
{
Span<float> amountsSpan = amounts.GetSpan();
int offsetY = y - startY;
int offsetX = minX - startX;
for (int i = 0; i < width; i++)
{
float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY));
amountsSpan[i] = (this.GraphicsOptions.BlendPercentage * (.9F * (distance / maxDistance))).Clamp(0, 1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(source.MemoryAllocator, destination, destination, rowColors.GetSpan(), amountsSpan);
float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY));
amountsSpan[i] =
(this.GraphicsOptions.BlendPercentage * (.9F * (distance / maxDistance))).Clamp(
0,
1);
}
Span<TPixel> destination = source.GetPixelRowSpan(offsetY).Slice(offsetX, width);
this.blender.Blend(
source.MemoryAllocator,
destination,
destination,
rowColors.GetSpan(),
amountsSpan);
});
}
}

1
src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs

@ -4,6 +4,7 @@
using System;
using System.Buffers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

1
src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs

@ -8,6 +8,7 @@ using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;

9
src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs

@ -9,6 +9,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -77,10 +78,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
if (this.Sampler is NearestNeighborResampler)
{
Parallel.For(
ParallelFor.WithConfiguration(
0,
height,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> destRow = destination.GetPixelRowSpan(y);
@ -115,10 +116,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using (Buffer2D<float> yBuffer = memoryAllocator.Allocate2D<float>(yLength, height))
using (Buffer2D<float> xBuffer = memoryAllocator.Allocate2D<float>(xLength, height))
{
Parallel.For(
ParallelFor.WithConfiguration(
0,
height,
configuration.ParallelOptions,
configuration,
y =>
{
ref TPixel destRowRef = ref MemoryMarshal.GetReference(destination.GetPixelRowSpan(y));

4
src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs

@ -58,10 +58,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X);
int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right);
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y).Slice(minX);

9
src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs

@ -4,6 +4,7 @@
using System;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -58,10 +59,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using (Buffer2D<TPixel> targetPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size()))
{
Parallel.For(
ParallelFor.WithConfiguration(
0,
halfHeight,
configuration.ParallelOptions,
configuration,
y =>
{
int newY = height - y - 1;
@ -91,10 +92,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using (Buffer2D<TPixel> targetPixels = configuration.MemoryAllocator.Allocate2D<TPixel>(source.Size()))
{
Parallel.For(
ParallelFor.WithConfiguration(
0,
height,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

9
src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs

@ -9,6 +9,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -74,10 +75,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
if (this.Sampler is NearestNeighborResampler)
{
Parallel.For(
ParallelFor.WithConfiguration(
0,
height,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> destRow = destination.GetPixelRowSpan(y);
@ -120,10 +121,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using (Buffer2D<float> yBuffer = memoryAllocator.Allocate2D<float>(yLength, height))
using (Buffer2D<float> xBuffer = memoryAllocator.Allocate2D<float>(xLength, height))
{
Parallel.For(
ParallelFor.WithConfiguration(
0,
height,
configuration.ParallelOptions,
configuration,
y =>
{
ref TPixel destRowRef = ref MemoryMarshal.GetReference(destination.GetPixelRowSpan(y));

9
src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs

@ -10,6 +10,7 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -270,10 +271,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
// Y coordinates of source points
@ -331,10 +332,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
});
// Now process the rows.
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
// Ensure offsets are normalized for cropping and padding.

12
src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs

@ -147,10 +147,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int height = source.Height;
Rectangle destinationBounds = destination.Bounds();
Parallel.For(
ParallelFor.WithConfiguration(
0,
height,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);
@ -179,10 +179,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int width = source.Width;
int height = source.Height;
Parallel.For(
ParallelFor.WithConfiguration(
0,
height,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);
@ -207,10 +207,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int height = source.Height;
Rectangle destinationBounds = destination.Bounds();
Parallel.For(
ParallelFor.WithConfiguration(
0,
height,
configuration.ParallelOptions,
configuration,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

2
src/ImageSharp/Processing/Processors/Transforms/WeightsBuffer.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms

2
src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs

@ -6,6 +6,8 @@ using System.Buffers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms

62
tests/ImageSharp.Benchmarks/Codecs/CopyPixels.cs

@ -1,19 +1,17 @@
// <copyright file="CopyPixels.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
using System;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
using System;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Advanced;
using SixLabors.Memory;
public class CopyPixels : BenchmarkBase
{
[Benchmark(Baseline = true, Description = "PixelAccessor Copy by indexer")]
@ -24,10 +22,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
Buffer2D<Rgba32> sourcePixels = source.GetRootFramePixelBuffer();
Buffer2D<Rgba32> targetPixels = target.GetRootFramePixelBuffer();
Parallel.For(
ParallelFor.WithConfiguration(
0,
source.Height,
Configuration.Default.ParallelOptions,
Configuration.Default,
y =>
{
for (int x = 0; x < source.Width; x++)
@ -48,10 +46,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
Buffer2D<Rgba32> sourcePixels = source.GetRootFramePixelBuffer();
Buffer2D<Rgba32> targetPixels = target.GetRootFramePixelBuffer();
Parallel.For(
ParallelFor.WithConfiguration(
0,
source.Height,
Configuration.Default.ParallelOptions,
Configuration.Default,
y =>
{
Span<Rgba32> sourceRow = sourcePixels.GetRowSpan(y);
@ -73,17 +71,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
using (var source = new Image<Rgba32>(1024, 768))
using (var target = new Image<Rgba32>(1024, 768))
{
Parallel.For(
ParallelFor.WithConfiguration(
0,
source.Height,
Configuration.Default.ParallelOptions,
Configuration.Default,
y =>
{
for (int x = 0; x < source.Width; x++)
{
target[x, y] = source[x, y];
}
});
for (int x = 0; x < source.Width; x++)
{
target[x, y] = source[x, y];
}
});
return target[0, 0];
}
@ -95,23 +93,23 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
using (var source = new Image<Rgba32>(1024, 768))
using (var target = new Image<Rgba32>(1024, 768))
{
Parallel.For(
ParallelFor.WithConfiguration(
0,
source.Height,
Configuration.Default.ParallelOptions,
Configuration.Default,
y =>
{
Span<Rgba32> sourceRow = source.Frames.RootFrame.GetPixelRowSpan(y);
Span<Rgba32> targetRow = target.Frames.RootFrame.GetPixelRowSpan(y);
for (int x = 0; x < source.Width; x++)
{
targetRow[x] = sourceRow[x];
}
});
Span<Rgba32> sourceRow = source.Frames.RootFrame.GetPixelRowSpan(y);
Span<Rgba32> targetRow = target.Frames.RootFrame.GetPixelRowSpan(y);
for (int x = 0; x < source.Width; x++)
{
targetRow[x] = sourceRow[x];
}
});
return target[0, 0];
}
}
}
}
}

2
tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave.cs

@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[GlobalSetup]
public void Setup()
{
this.configuration.ParallelOptions.MaxDegreeOfParallelism =
this.configuration.MaxDegreeOfParallelism =
this.EnableParallelExecution ? Environment.ProcessorCount : 1;
if (this.sourceBytes == null)

17
tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs

@ -1,14 +1,16 @@
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
using System;
using System.Numerics;
using System;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
[Config(typeof(Config.ShortClr))]
public class YCbCrColorConversion
{
@ -81,6 +83,5 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
return buffers;
}
}
}

5
tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// ReSharper disable InconsistentNaming
using System.Buffers;
@ -7,7 +10,7 @@ using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk

5
tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// ReSharper disable InconsistentNaming
using System.Buffers;
@ -5,7 +8,7 @@ using System;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk

5
tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// ReSharper disable InconsistentNaming
using System.Buffers;
@ -6,7 +9,7 @@ using System.Numerics;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk

5
tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs

@ -1,3 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// ReSharper disable InconsistentNaming
using System.Buffers;
@ -5,7 +8,7 @@ using System;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk

7
tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs

@ -1,8 +1,11 @@
using System;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
// ReSharper disable InconsistentNaming

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

@ -18,7 +18,7 @@
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.10.14" />
<PackageReference Include="Colourful" Version="2.0.0" />
<PackageReference Include="SixLabors.Shapes.Text" Version="1.0.0-dev000081" />
<PackageReference Include="SixLabors.Shapes.Text" Version="1.0.0-beta0007" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0" />
</ItemGroup>

40
tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs

@ -1,32 +1,35 @@
// <copyright file="Crop.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
using System;
using System.Buffers;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.PixelFormats.PixelBlenders;
namespace SixLabors.ImageSharp.Benchmarks
{
using System;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using CoreSize = SixLabors.Primitives.Size;
using System.Numerics;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats.PixelBlenders;
public class PorterDuffBulkVsPixel : BenchmarkBase
{
private void BulkVectorConvert<TPixel>(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount)
private void BulkVectorConvert<TPixel>(
Span<TPixel> destination,
Span<TPixel> background,
Span<TPixel> source,
Span<float> amount)
where TPixel : struct, IPixel<TPixel>
{
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length));
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IMemoryOwner<Vector4> buffer = Configuration.Default.MemoryAllocator.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer =
Configuration.Default.MemoryAllocator.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -43,8 +46,13 @@ namespace SixLabors.ImageSharp.Benchmarks
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length);
}
}
private void BulkPixelConvert<TPixel>(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount)
where TPixel : struct, IPixel<TPixel>
private void BulkPixelConvert<TPixel>(
Span<TPixel> destination,
Span<TPixel> background,
Span<TPixel> source,
Span<float> amount)
where TPixel : struct, IPixel<TPixel>
{
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination));
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination));
@ -97,4 +105,4 @@ namespace SixLabors.ImageSharp.Benchmarks
}
}
}
}
}

74
tests/ImageSharp.Benchmarks/Samplers/Glow.cs

@ -1,29 +1,27 @@
// <copyright file="Crop.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
using System;
using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
namespace SixLabors.ImageSharp.Benchmarks
{
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.ImageSharp.Processing.Processors.Overlays;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Benchmarks
{
using CoreSize = SixLabors.Primitives.Size;
using System.Numerics;
using System;
using System.Threading.Tasks;
using SixLabors.Memory;
using SixLabors.Primitives;
using SixLabors.ImageSharp.Processing.Processors.Overlays;
using SixLabors.ImageSharp.Processing.Processors;
public class Glow : BenchmarkBase
{
private GlowProcessor<Rgba32> bulk;
private GlowProcessorParallel<Rgba32> parallel;
[GlobalSetup]
@ -31,8 +29,8 @@ namespace SixLabors.ImageSharp.Benchmarks
{
this.bulk = new GlowProcessor<Rgba32>(NamedColors<Rgba32>.Beige, 800 * .5f, GraphicsOptions.Default);
this.parallel = new GlowProcessorParallel<Rgba32>(NamedColors<Rgba32>.Beige) { Radius = 800 * .5f, };
}
[Benchmark(Description = "ImageSharp Glow - Bulk")]
public CoreSize GlowBulk()
{
@ -76,7 +74,10 @@ namespace SixLabors.ImageSharp.Benchmarks
public float Radius { get; set; }
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
protected override void OnFrameApply(
ImageFrame<TPixel> source,
Rectangle sourceRectangle,
Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
@ -84,7 +85,9 @@ namespace SixLabors.ImageSharp.Benchmarks
int endX = sourceRectangle.Right;
TPixel glowColor = this.GlowColor;
Vector2 centre = Rectangle.Center(sourceRectangle);
float maxDistance = this.Radius > 0 ? Math.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
float maxDistance = this.Radius > 0
? Math.Min(this.Radius, sourceRectangle.Width * .5F)
: sourceRectangle.Width * .5F;
// Align start/end positions.
int minX = Math.Max(0, startX);
@ -109,26 +112,31 @@ namespace SixLabors.ImageSharp.Benchmarks
Buffer2D<TPixel> sourcePixels = source.PixelBuffer;
rowColors.GetSpan().Fill(glowColor);
Parallel.For(
ParallelFor.WithConfiguration(
minY,
maxY,
configuration.ParallelOptions,
configuration,
y =>
{
int offsetY = y - startY;
for (int x = minX; x < maxX; x++)
{
int offsetX = x - startX;
float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY));
Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4();
TPixel packed = default(TPixel);
packed.PackFromVector4(PremultipliedLerp(sourceColor, glowColor.ToVector4(), 1 - (.95F * (distance / maxDistance))));
sourcePixels[offsetX, offsetY] = packed;
}
});
int offsetY = y - startY;
for (int x = minX; x < maxX; x++)
{
int offsetX = x - startX;
float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY));
Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4();
TPixel packed = default(TPixel);
packed.PackFromVector4(
PremultipliedLerp(
sourceColor,
glowColor.ToVector4(),
1 - (.95F * (distance / maxDistance))));
sourcePixels[offsetX, offsetY] = packed;
}
});
}
}
public static Vector4 PremultipliedLerp(Vector4 backdrop, Vector4 source, float amount)
{
amount = amount.Clamp(0, 1);
@ -162,4 +170,4 @@ namespace SixLabors.ImageSharp.Benchmarks
}
}
}
}
}

2
tests/ImageSharp.Benchmarks/Samplers/Resize.cs

@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Benchmarks
[GlobalSetup]
public void Setup()
{
this.configuration.ParallelOptions.MaxDegreeOfParallelism =
this.configuration.MaxDegreeOfParallelism =
this.EnableParallelExecution ? Environment.ProcessorCount : 1;
}

25
tests/ImageSharp.Tests/ConfigurationTests.cs

@ -10,6 +10,7 @@ using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.PixelFormats;
using Moq;
using Xunit;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests
{
@ -45,15 +46,6 @@ namespace SixLabors.ImageSharp.Tests
Assert.True(Configuration.Default != null);
}
/// <summary>
/// Test that the default configuration parallel options is not null.
/// </summary>
[Fact]
public void TestDefaultConfigurationParallelOptionsIsNotNull()
{
Assert.True(Configuration.Default.ParallelOptions != null);
}
/// <summary>
/// Test that the default configuration read origin options is set to begin.
/// </summary>
@ -70,9 +62,22 @@ namespace SixLabors.ImageSharp.Tests
[Fact]
public void TestDefaultConfigurationMaxDegreeOfParallelism()
{
Assert.True(Configuration.Default.ParallelOptions.MaxDegreeOfParallelism == Environment.ProcessorCount);
Assert.True(Configuration.Default.MaxDegreeOfParallelism == Environment.ProcessorCount);
var cfg = new Configuration();
Assert.True(cfg.MaxDegreeOfParallelism == Environment.ProcessorCount);
}
[Theory]
[InlineData(0)]
[InlineData(-42)]
public void Set_MaxDegreeOfParallelism_ToNonPositiveValue_Throws(int value)
{
var cfg = new Configuration();
Assert.Throws<ArgumentOutOfRangeException>(() => cfg.MaxDegreeOfParallelism = value);
}
[Fact]
public void ConstructorCallConfigureOnFormatProvider()
{

3
tests/ImageSharp.Tests/Drawing/BeziersTests.cs

@ -3,9 +3,10 @@
using System.Numerics;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Memory;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing

4
tests/ImageSharp.Tests/Drawing/DrawPathTests.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Shapes;
@ -9,8 +11,6 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing
{
using SixLabors.Memory;
public class DrawPathTests : FileTestBase
{
[Fact]

4
tests/ImageSharp.Tests/Drawing/FillPatternTests.cs

@ -2,10 +2,12 @@
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing;
using SixLabors.Memory;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing

4
tests/ImageSharp.Tests/Drawing/LineComplexPolygonTests.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Shapes;
@ -10,8 +12,6 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing
{
using SixLabors.Memory;
public class LineComplexPolygonTests : FileTestBase
{
[Fact]

3
tests/ImageSharp.Tests/Drawing/LineTests.cs

@ -3,6 +3,7 @@
using System.Numerics;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
@ -10,8 +11,6 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Drawing
{
using SixLabors.Memory;
public class LineTests : FileTestBase
{
[Fact]

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

Loading…
Cancel
Save