Browse Source

- Explicitly pass MemoryManager to the places that

need it (aside from a few exceptions)
af/merge-core
Lauri Kotilainen 8 years ago
parent
commit
8d44ae346e
  1. 4
      src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs
  2. 4
      src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs
  3. 4
      src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
  4. 4
      src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs
  5. 4
      src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs
  6. 2
      src/ImageSharp.Drawing/Paths/DrawPath.cs
  7. 4
      src/ImageSharp.Drawing/Paths/FillPaths.cs
  8. 6
      src/ImageSharp.Drawing/Paths/ShapePath.cs
  9. 7
      src/ImageSharp.Drawing/Paths/ShapeRegion.cs
  10. 2
      src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs
  11. 2
      src/ImageSharp.Drawing/Processors/FillProcessor.cs
  12. 2
      src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
  13. 5
      src/ImageSharp/Configuration.cs
  14. 4
      src/ImageSharp/DefaultInternalImageProcessorContext.cs
  15. 6
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  16. 6
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  17. 4
      src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegComponentPostProcessor.cs
  18. 6
      src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs
  19. 4
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
  20. 4
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
  21. 6
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs
  22. 14
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
  23. 9
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsJpegPixelArea.cs
  24. 7
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsQuantizationTables.cs
  25. 18
      src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs
  26. 8
      src/ImageSharp/Formats/Png/PngConfigurationModule.cs
  27. 14
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  28. 11
      src/ImageSharp/Formats/Png/PngEncoder.cs
  29. 19
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  30. 3
      src/ImageSharp/IImageProcessingContext{TPixel}.cs
  31. 2
      src/ImageSharp/Image/Image.Decode.cs
  32. 2
      src/ImageSharp/Image/ImageFrame.LoadPixelData.cs
  33. 4
      src/ImageSharp/Image/ImageFrameCollection.cs
  34. 21
      src/ImageSharp/Image/ImageFrame{TPixel}.cs
  35. 2
      src/ImageSharp/Image/PixelAccessor{TPixel}.cs
  36. 2
      src/ImageSharp/Image/PixelArea{TPixel}.cs
  37. 18
      src/ImageSharp/Memory/Buffer2D{T}.cs
  38. 5
      src/ImageSharp/Memory/MemoryManager.cs
  39. 42
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
  40. 2
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt
  41. 4
      src/ImageSharp/Processing/ColorMatrix/Lomograph.cs
  42. 4
      src/ImageSharp/Processing/ColorMatrix/Polaroid.cs
  43. 4
      src/ImageSharp/Processing/Effects/BackgroundColor.cs
  44. 4
      src/ImageSharp/Processing/Overlays/Glow.cs
  45. 4
      src/ImageSharp/Processing/Overlays/Vignette.cs
  46. 11
      src/ImageSharp/Processing/Processors/ColorMatrix/LomographProcessor.cs
  47. 13
      src/ImageSharp/Processing/Processors/ColorMatrix/PolaroidProcessor.cs
  48. 9
      src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs
  49. 9
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  50. 12
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  51. 4
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs
  52. 12
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs
  53. 14
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  54. 4
      src/ImageSharp/Processing/Transforms/Resize.cs
  55. 6
      tests/ImageSharp.Tests/FakeImageOperationsProvider.cs

4
src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs

@ -122,8 +122,8 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
internal override void Apply(Span<float> scanline, int x, int y) internal override void Apply(Span<float> scanline, int x, int y)
{ {
// Create a span for colors // Create a span for colors
using (var amountBuffer = MemoryManager.Current.Allocate<float>(scanline.Length)) using (var amountBuffer = this.Target.MemoryManager.Allocate<float>(scanline.Length))
using (var overlay = MemoryManager.Current.Allocate<TPixel>(scanline.Length)) using (var overlay = this.Target.MemoryManager.Allocate<TPixel>(scanline.Length))
{ {
int sourceY = (y - this.offsetY) % this.yLength; int sourceY = (y - this.offsetY) % this.yLength;
int offsetX = x - this.offsetX; int offsetX = x - this.offsetX;

4
src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs

@ -152,8 +152,8 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
internal override void Apply(Span<float> scanline, int x, int y) internal override void Apply(Span<float> scanline, int x, int y)
{ {
int patternY = y % this.pattern.Height; int patternY = y % this.pattern.Height;
using (var amountBuffer = MemoryManager.Current.Allocate<float>(scanline.Length)) using (var amountBuffer = this.Target.MemoryManager.Allocate<float>(scanline.Length))
using (var overlay = MemoryManager.Current.Allocate<TPixel>(scanline.Length)) using (var overlay = this.Target.MemoryManager.Allocate<TPixel>(scanline.Length))
{ {
for (int i = 0; i < scanline.Length; i++) for (int i = 0; i < scanline.Length; i++)
{ {

4
src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs

@ -65,8 +65,8 @@ namespace SixLabors.ImageSharp.Drawing.Brushes.Processors
/// <remarks>scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs.</remarks> /// <remarks>scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs.</remarks>
internal virtual void Apply(Span<float> scanline, int x, int y) internal virtual void Apply(Span<float> scanline, int x, int y)
{ {
using (var amountBuffer = MemoryManager.Current.Allocate<float>(scanline.Length)) using (var amountBuffer = this.Target.MemoryManager.Allocate<float>(scanline.Length))
using (var overlay = MemoryManager.Current.Allocate<TPixel>(scanline.Length)) using (var overlay = this.Target.MemoryManager.Allocate<TPixel>(scanline.Length))
{ {
for (int i = 0; i < scanline.Length; i++) for (int i = 0; i < scanline.Length; i++)
{ {

4
src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs

@ -144,8 +144,8 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
/// <inheritdoc /> /// <inheritdoc />
internal override void Apply(Span<float> scanline, int x, int y) internal override void Apply(Span<float> scanline, int x, int y)
{ {
using (var amountBuffer = MemoryManager.Current.Allocate<float>(scanline.Length)) using (var amountBuffer = this.Target.MemoryManager.Allocate<float>(scanline.Length))
using (var overlay = MemoryManager.Current.Allocate<TPixel>(scanline.Length)) using (var overlay = this.Target.MemoryManager.Allocate<TPixel>(scanline.Length))
{ {
for (int i = 0; i < scanline.Length; i++) for (int i = 0; i < scanline.Length; i++)
{ {

4
src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs

@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
public SolidBrushApplicator(ImageFrame<TPixel> source, TPixel color, GraphicsOptions options) public SolidBrushApplicator(ImageFrame<TPixel> source, TPixel color, GraphicsOptions options)
: base(source, options) : base(source, options)
{ {
this.Colors = MemoryManager.Current.Allocate<TPixel>(source.Width); this.Colors = source.MemoryManager.Allocate<TPixel>(source.Width);
for (int i = 0; i < this.Colors.Length; i++) for (int i = 0; i < this.Colors.Length; i++)
{ {
this.Colors[i] = color; this.Colors[i] = color;
@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
{ {
Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length); Span<TPixel> destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
using (var amountBuffer = MemoryManager.Current.Allocate<float>(scanline.Length)) using (var amountBuffer = this.Target.MemoryManager.Allocate<float>(scanline.Length))
{ {
for (int i = 0; i < scanline.Length; i++) for (int i = 0; i < scanline.Length; i++)
{ {

2
src/ImageSharp.Drawing/Paths/DrawPath.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp
public static IImageProcessingContext<TPixel> Draw<TPixel>(this IImageProcessingContext<TPixel> source, IPen<TPixel> pen, IPath path, GraphicsOptions options) public static IImageProcessingContext<TPixel> Draw<TPixel>(this IImageProcessingContext<TPixel> source, IPen<TPixel> pen, IPath path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
return source.Fill(pen.StrokeFill, new ShapePath(path, pen), options); return source.Fill(pen.StrokeFill, new ShapePath(source.GetMemoryManager(), path, pen), options);
} }
/// <summary> /// <summary>

4
src/ImageSharp.Drawing/Paths/FillPaths.cs

@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp
public static IImageProcessingContext<TPixel> Fill<TPixel>(this IImageProcessingContext<TPixel> source, IBrush<TPixel> brush, IPath path, GraphicsOptions options) public static IImageProcessingContext<TPixel> Fill<TPixel>(this IImageProcessingContext<TPixel> source, IBrush<TPixel> brush, IPath path, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
return source.Fill(brush, new ShapeRegion(path), options); return source.Fill(brush, new ShapeRegion(source.GetMemoryManager(), path), options);
} }
/// <summary> /// <summary>
@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp
public static IImageProcessingContext<TPixel> Fill<TPixel>(this IImageProcessingContext<TPixel> source, IBrush<TPixel> brush, IPath path) public static IImageProcessingContext<TPixel> Fill<TPixel>(this IImageProcessingContext<TPixel> source, IBrush<TPixel> brush, IPath path)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
return source.Fill(brush, new ShapeRegion(path), GraphicsOptions.Default); return source.Fill(brush, new ShapeRegion(source.GetMemoryManager(), path), GraphicsOptions.Default);
} }
/// <summary> /// <summary>

6
src/ImageSharp.Drawing/Paths/ShapePath.cs

@ -4,6 +4,8 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.Memory;
using SixLabors.Shapes; using SixLabors.Shapes;
namespace SixLabors.ImageSharp.Drawing namespace SixLabors.ImageSharp.Drawing
@ -19,8 +21,8 @@ namespace SixLabors.ImageSharp.Drawing
/// <param name="shape">The shape.</param> /// <param name="shape">The shape.</param>
/// <param name="pen">The pen to apply to the shape.</param> /// <param name="pen">The pen to apply to the shape.</param>
// SixLabors.shape willbe moving to a Span/ReadOnlySpan based API shortly use ToArray for now. // SixLabors.shape willbe moving to a Span/ReadOnlySpan based API shortly use ToArray for now.
public ShapePath(IPath shape, Pens.IPen pen) public ShapePath(MemoryManager memoryManager, IPath shape, Pens.IPen pen)
: base(shape.GenerateOutline(pen.StrokeWidth, pen.StrokePattern.ToArray())) : base(memoryManager, shape.GenerateOutline(pen.StrokeWidth, pen.StrokePattern.ToArray()))
{ {
} }
} }

7
src/ImageSharp.Drawing/Paths/ShapeRegion.cs

@ -15,12 +15,15 @@ namespace SixLabors.ImageSharp.Drawing
/// </summary> /// </summary>
internal class ShapeRegion : Region internal class ShapeRegion : Region
{ {
private readonly MemoryManager memoryManager;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ShapeRegion"/> class. /// Initializes a new instance of the <see cref="ShapeRegion"/> class.
/// </summary> /// </summary>
/// <param name="shape">The shape.</param> /// <param name="shape">The shape.</param>
public ShapeRegion(IPath shape) public ShapeRegion(MemoryManager memoryManager, IPath shape)
{ {
this.memoryManager = memoryManager;
this.Shape = shape.AsClosedPath(); this.Shape = shape.AsClosedPath();
int left = (int)MathF.Floor(shape.Bounds.Left); int left = (int)MathF.Floor(shape.Bounds.Left);
int top = (int)MathF.Floor(shape.Bounds.Top); int top = (int)MathF.Floor(shape.Bounds.Top);
@ -46,7 +49,7 @@ namespace SixLabors.ImageSharp.Drawing
{ {
var start = new PointF(this.Bounds.Left - 1, y); var start = new PointF(this.Bounds.Left - 1, y);
var end = new PointF(this.Bounds.Right + 1, y); var end = new PointF(this.Bounds.Right + 1, y);
using (var innerBuffer = MemoryManager.Current.Allocate<PointF>(buffer.Length)) using (var innerBuffer = this.memoryManager.Allocate<PointF>(buffer.Length))
{ {
PointF[] array = innerBuffer.Array; PointF[] array = innerBuffer.Array;
int count = this.Shape.FindIntersections(start, end, array, 0); int count = this.Shape.FindIntersections(start, end, array, 0);

2
src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs

@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
maxY = Math.Min(this.Location.Y + this.Size.Height, maxY); maxY = Math.Min(this.Location.Y + this.Size.Height, maxY);
int width = maxX - minX; int width = maxX - minX;
using (var amount = MemoryManager.Current.Allocate<float>(width)) using (var amount = this.Image.GetConfiguration().MemoryManager.Allocate<float>(width))
{ {
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
{ {

2
src/ImageSharp.Drawing/Processors/FillProcessor.cs

@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
int width = maxX - minX; int width = maxX - minX;
using (var amount = MemoryManager.Current.Allocate<float>(width)) using (var amount = source.MemoryManager.Allocate<float>(width))
using (BrushApplicator<TPixel> applicator = this.brush.CreateApplicator(source, sourceRectangle, this.options)) using (BrushApplicator<TPixel> applicator = this.brush.CreateApplicator(source, sourceRectangle, this.options))
{ {
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)

2
src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs

@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
{ {
float[] buffer = arrayPool.Rent(maxIntersections); float[] buffer = arrayPool.Rent(maxIntersections);
int scanlineWidth = maxX - minX; int scanlineWidth = maxX - minX;
using (var scanline = MemoryManager.Current.Allocate<float>(scanlineWidth)) using (var scanline = source.MemoryManager.Allocate<float>(scanlineWidth))
{ {
try try
{ {

5
src/ImageSharp/Configuration.cs

@ -83,6 +83,11 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
public IEnumerable<IImageFormat> ImageFormats => this.imageFormats; public IEnumerable<IImageFormat> ImageFormats => this.imageFormats;
/// <summary>
/// Gets or sets the <see cref="MemoryManager"/> that is currently in use.
/// </summary>
public MemoryManager MemoryManager { get; set; } = new ArrayPoolMemoryManager(1024 * 80);
/// <summary> /// <summary>
/// Gets the maximum header size of all the formats. /// Gets the maximum header size of all the formats.
/// </summary> /// </summary>

4
src/ImageSharp/DefaultInternalImageProcessorContext.cs

@ -1,7 +1,9 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -72,5 +74,7 @@ namespace SixLabors.ImageSharp
{ {
return this.ApplyProcessor(processor, this.source.Bounds()); return this.ApplyProcessor(processor, this.source.Bounds());
} }
public MemoryManager GetMemoryManager() => this.source.GetConfiguration().MemoryManager;
} }
} }

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

@ -263,7 +263,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
var color = default(TPixel); var color = default(TPixel);
var rgba = new Rgba32(0, 0, 0, 255); var rgba = new Rgba32(0, 0, 0, 255);
using (var buffer = Buffer2D<byte>.CreateClean(width, height)) using (var buffer = this.configuration.MemoryManager.Allocate2D<byte>(width, height, true))
{ {
this.UncompressRle8(width, buffer.Span); this.UncompressRle8(width, buffer.Span);
@ -385,7 +385,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
padding = 4 - padding; padding = 4 - padding;
} }
using (var row = MemoryManager.Current.Allocate<byte>(arrayWidth + padding, true)) using (var row = this.configuration.MemoryManager.Allocate<byte>(arrayWidth + padding, true))
{ {
var color = default(TPixel); var color = default(TPixel);
var rgba = new Rgba32(0, 0, 0, 255); var rgba = new Rgba32(0, 0, 0, 255);
@ -435,7 +435,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
var color = default(TPixel); var color = default(TPixel);
var rgba = new Rgba32(0, 0, 0, 255); var rgba = new Rgba32(0, 0, 0, 255);
using (var buffer = MemoryManager.Current.Allocate<byte>(stride)) using (var buffer = this.configuration.MemoryManager.Allocate<byte>(stride))
{ {
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {

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

@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (this.logicalScreenDescriptor.GlobalColorTableFlag) if (this.logicalScreenDescriptor.GlobalColorTableFlag)
{ {
this.globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3; this.globalColorTableLength = this.logicalScreenDescriptor.GlobalColorTableSize * 3;
this.globalColorTable = MemoryManager.Current.Allocate<byte>(this.globalColorTableLength, true); this.globalColorTable = this.configuration.MemoryManager.Allocate<byte>(this.globalColorTableLength, true);
// Read the global color table from the stream // Read the global color table from the stream
stream.Read(this.globalColorTable.Array, 0, this.globalColorTableLength); stream.Read(this.globalColorTable.Array, 0, this.globalColorTableLength);
@ -320,11 +320,11 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (imageDescriptor.LocalColorTableFlag) if (imageDescriptor.LocalColorTableFlag)
{ {
int length = imageDescriptor.LocalColorTableSize * 3; int length = imageDescriptor.LocalColorTableSize * 3;
localColorTable = MemoryManager.Current.Allocate<byte>(length, true); localColorTable = this.configuration.MemoryManager.Allocate<byte>(length, true);
this.currentStream.Read(localColorTable.Array, 0, length); this.currentStream.Read(localColorTable.Array, 0, length);
} }
indices = MemoryManager.Current.Allocate<byte>(imageDescriptor.Width * imageDescriptor.Height, true); indices = this.configuration.MemoryManager.Allocate<byte>(imageDescriptor.Width * imageDescriptor.Height, true);
this.ReadFrameIndices(imageDescriptor, indices); this.ReadFrameIndices(imageDescriptor, indices);
this.ReadFrameColors(indices, localColorTable ?? this.globalColorTable, imageDescriptor); this.ReadFrameColors(indices, localColorTable ?? this.globalColorTable, imageDescriptor);

4
src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegComponentPostProcessor.cs

@ -22,11 +22,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JpegComponentPostProcessor"/> class. /// Initializes a new instance of the <see cref="JpegComponentPostProcessor"/> class.
/// </summary> /// </summary>
public JpegComponentPostProcessor(JpegImagePostProcessor imagePostProcessor, IJpegComponent component) public JpegComponentPostProcessor(MemoryManager memoryManager, JpegImagePostProcessor imagePostProcessor, IJpegComponent component)
{ {
this.Component = component; this.Component = component;
this.ImagePostProcessor = imagePostProcessor; this.ImagePostProcessor = imagePostProcessor;
this.ColorBuffer = MemoryManager.Current.Allocate2D<float>( this.ColorBuffer = memoryManager.Allocate2D<float>(
imagePostProcessor.PostProcessorBufferSize.Width, imagePostProcessor.PostProcessorBufferSize.Width,
imagePostProcessor.PostProcessorBufferSize.Height); imagePostProcessor.PostProcessorBufferSize.Height);

6
src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs

@ -45,15 +45,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
/// Initializes a new instance of the <see cref="JpegImagePostProcessor"/> class. /// Initializes a new instance of the <see cref="JpegImagePostProcessor"/> class.
/// </summary> /// </summary>
/// <param name="rawJpeg">The <see cref="IRawJpegData"/> representing the uncompressed spectral Jpeg data</param> /// <param name="rawJpeg">The <see cref="IRawJpegData"/> representing the uncompressed spectral Jpeg data</param>
public JpegImagePostProcessor(IRawJpegData rawJpeg) public JpegImagePostProcessor(MemoryManager memoryManager, IRawJpegData rawJpeg)
{ {
this.RawJpeg = rawJpeg; this.RawJpeg = rawJpeg;
IJpegComponent c0 = rawJpeg.Components.First(); IJpegComponent c0 = rawJpeg.Components.First();
this.NumberOfPostProcessorSteps = c0.SizeInBlocks.Height / BlockRowsPerStep; this.NumberOfPostProcessorSteps = c0.SizeInBlocks.Height / BlockRowsPerStep;
this.PostProcessorBufferSize = new Size(c0.SizeInBlocks.Width * 8, PixelRowsPerStep); this.PostProcessorBufferSize = new Size(c0.SizeInBlocks.Width * 8, PixelRowsPerStep);
this.ComponentProcessors = rawJpeg.Components.Select(c => new JpegComponentPostProcessor(this, c)).ToArray(); this.ComponentProcessors = rawJpeg.Components.Select(c => new JpegComponentPostProcessor(memoryManager, this, c)).ToArray();
this.rgbaBuffer = MemoryManager.Current.Allocate<Vector4>(rawJpeg.ImageSizeInPixels.Width); this.rgbaBuffer = memoryManager.Allocate<Vector4>(rawJpeg.ImageSizeInPixels.Width);
this.colorConverter = ColorConverters.JpegColorConverter.GetConverter(rawJpeg.ColorSpace); this.colorConverter = ColorConverters.JpegColorConverter.GetConverter(rawJpeg.ColorSpace);
} }

4
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs

@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// Initializes <see cref="SpectralBlocks"/> /// Initializes <see cref="SpectralBlocks"/>
/// </summary> /// </summary>
/// <param name="decoder">The <see cref="OrigJpegDecoderCore"/> instance</param> /// <param name="decoder">The <see cref="OrigJpegDecoderCore"/> instance</param>
public void InitializeDerivedData(OrigJpegDecoderCore decoder) public void InitializeDerivedData(MemoryManager memoryManager, OrigJpegDecoderCore decoder)
{ {
// For 4-component images (either CMYK or YCbCrK), we only support two // For 4-component images (either CMYK or YCbCrK), we only support two
// hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22]. // hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22].
@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors); this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors);
} }
this.SpectralBlocks = Buffer2D<Block8x8>.CreateClean(this.SizeInBlocks); this.SpectralBlocks = memoryManager.Allocate2D<Block8x8>(this.SizeInBlocks.Width, this.SizeInBlocks.Height, true);
} }
/// <summary> /// <summary>

4
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs

@ -659,7 +659,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
foreach (OrigComponent component in this.Components) foreach (OrigComponent component in this.Components)
{ {
component.InitializeDerivedData(this); component.InitializeDerivedData(this.configuration.MemoryManager, this);
} }
this.ColorSpace = this.DeduceJpegColorSpace(); this.ColorSpace = this.DeduceJpegColorSpace();
@ -767,7 +767,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
private Image<TPixel> PostProcessIntoImage<TPixel>() private Image<TPixel> PostProcessIntoImage<TPixel>()
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
using (var postProcessor = new JpegImagePostProcessor(this)) using (var postProcessor = new JpegImagePostProcessor(this.configuration.MemoryManager, this))
{ {
var image = new Image<TPixel>(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData); var image = new Image<TPixel>(this.configuration, this.ImageWidth, this.ImageHeight, this.MetaData);
postProcessor.PostProcess(image.Frames.RootFrame); postProcessor.PostProcess(image.Frames.RootFrame);

6
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs

@ -15,10 +15,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary> /// </summary>
internal class PdfJsFrameComponent : IDisposable, IJpegComponent internal class PdfJsFrameComponent : IDisposable, IJpegComponent
{ {
private readonly MemoryManager memoryManager;
#pragma warning disable SA1401 // Fields should be private #pragma warning disable SA1401 // Fields should be private
public PdfJsFrameComponent(PdfJsFrame frame, byte id, int horizontalFactor, int verticalFactor, byte quantizationTableIndex, int index) public PdfJsFrameComponent(MemoryManager memoryManager, PdfJsFrame frame, byte id, int horizontalFactor, int verticalFactor, byte quantizationTableIndex, int index)
{ {
this.memoryManager = memoryManager;
this.Frame = frame; this.Frame = frame;
this.Id = id; this.Id = id;
this.HorizontalSamplingFactor = horizontalFactor; this.HorizontalSamplingFactor = horizontalFactor;
@ -114,7 +116,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
int blocksBufferSize = 64 * this.BlocksPerColumnForMcu * (this.BlocksPerLineForMcu + 1); int blocksBufferSize = 64 * this.BlocksPerColumnForMcu * (this.BlocksPerLineForMcu + 1);
// Pooled. Disposed via frame disposal // Pooled. Disposed via frame disposal
this.BlockData = MemoryManager.Current.Allocate<short>(blocksBufferSize, true); this.BlockData = this.memoryManager.Allocate<short>(blocksBufferSize, true);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

14
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs

@ -22,14 +22,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary> /// </summary>
/// <param name="lengths">The code lengths</param> /// <param name="lengths">The code lengths</param>
/// <param name="values">The huffman values</param> /// <param name="values">The huffman values</param>
public PdfJsHuffmanTable(byte[] lengths, byte[] values) public PdfJsHuffmanTable(MemoryManager memoryManager, byte[] lengths, byte[] values)
{ {
this.lookahead = MemoryManager.Current.Allocate<short>(256, true); this.lookahead = memoryManager.Allocate<short>(256, true);
this.valOffset = MemoryManager.Current.Allocate<short>(18, true); this.valOffset = memoryManager.Allocate<short>(18, true);
this.maxcode = MemoryManager.Current.Allocate<long>(18, true); this.maxcode = memoryManager.Allocate<long>(18, true);
using (var huffsize = MemoryManager.Current.Allocate<short>(257, true)) using (var huffsize = memoryManager.Allocate<short>(257, true))
using (var huffcode = MemoryManager.Current.Allocate<short>(257, true)) using (var huffcode = memoryManager.Allocate<short>(257, true))
{ {
GenerateSizeTable(lengths, huffsize); GenerateSizeTable(lengths, huffsize);
GenerateCodeTable(huffsize, huffcode); GenerateCodeTable(huffsize, huffcode);
@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
GenerateLookaheadTables(lengths, values, this.lookahead); GenerateLookaheadTables(lengths, values, this.lookahead);
} }
this.huffval = MemoryManager.Current.Allocate<byte>(values.Length, true); this.huffval = memoryManager.Allocate<byte>(values.Length, true);
Buffer.BlockCopy(values, 0, this.huffval.Array, 0, values.Length); Buffer.BlockCopy(values, 0, this.huffval.Array, 0, values.Length);
this.MaxCode = this.maxcode.Array; this.MaxCode = this.maxcode.Array;

9
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsJpegPixelArea.cs

@ -14,6 +14,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary> /// </summary>
internal struct PdfJsJpegPixelArea : IDisposable internal struct PdfJsJpegPixelArea : IDisposable
{ {
private readonly MemoryManager memoryManager;
private readonly int imageWidth; private readonly int imageWidth;
private readonly int imageHeight; private readonly int imageHeight;
@ -28,8 +30,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// <param name="imageWidth">The image width</param> /// <param name="imageWidth">The image width</param>
/// <param name="imageHeight">The image height</param> /// <param name="imageHeight">The image height</param>
/// <param name="numberOfComponents">The number of components</param> /// <param name="numberOfComponents">The number of components</param>
public PdfJsJpegPixelArea(int imageWidth, int imageHeight, int numberOfComponents) public PdfJsJpegPixelArea(MemoryManager memoryManager, int imageWidth, int imageHeight, int numberOfComponents)
{ {
this.memoryManager = memoryManager;
this.imageWidth = imageWidth; this.imageWidth = imageWidth;
this.imageHeight = imageHeight; this.imageHeight = imageHeight;
this.Width = 0; this.Width = 0;
@ -69,11 +72,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.rowStride = width * numberOfComponents; this.rowStride = width * numberOfComponents;
var scale = new Vector2(this.imageWidth / (float)width, this.imageHeight / (float)height); var scale = new Vector2(this.imageWidth / (float)width, this.imageHeight / (float)height);
this.componentData = MemoryManager.Current.Allocate<byte>(width * height * numberOfComponents); this.componentData = this.memoryManager.Allocate<byte>(width * height * numberOfComponents);
Span<byte> componentDataSpan = this.componentData; Span<byte> componentDataSpan = this.componentData;
const uint Mask3Lsb = 0xFFFFFFF8; // Used to clear the 3 LSBs const uint Mask3Lsb = 0xFFFFFFF8; // Used to clear the 3 LSBs
using (var xScaleBlockOffset = MemoryManager.Current.Allocate<int>(width)) using (var xScaleBlockOffset = this.memoryManager.Allocate<int>(width))
{ {
Span<int> xScaleBlockOffsetSpan = xScaleBlockOffset; Span<int> xScaleBlockOffsetSpan = xScaleBlockOffset;
for (int i = 0; i < numberOfComponents; i++) for (int i = 0; i < numberOfComponents; i++)

7
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsQuantizationTables.cs

@ -40,6 +40,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
63 63
}; };
public PdfJsQuantizationTables(MemoryManager memoryManager)
{
this.Tables = memoryManager.Allocate2D<short>(64, 4);
}
/// <summary> /// <summary>
/// Gets or sets the quantization tables. /// Gets or sets the quantization tables.
/// </summary> /// </summary>
@ -49,8 +54,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
get; set; get; set;
} }
= MemoryManager.Current.Allocate2D<short>(64, 4);
/// <inheritdoc/> /// <inheritdoc/>
public void Dispose() public void Dispose()
{ {

18
src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs

@ -216,7 +216,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
ushort marker = this.ReadUint16(); ushort marker = this.ReadUint16();
fileMarker = new PdfJsFileMarker(marker, (int)this.InputStream.Position - 2); fileMarker = new PdfJsFileMarker(marker, (int)this.InputStream.Position - 2);
this.quantizationTables = new PdfJsQuantizationTables(); this.quantizationTables = new PdfJsQuantizationTables(this.configuration.MemoryManager);
this.dcHuffmanTables = new PdfJsHuffmanTables(); this.dcHuffmanTables = new PdfJsHuffmanTables();
this.acHuffmanTables = new PdfJsHuffmanTables(); this.acHuffmanTables = new PdfJsHuffmanTables();
@ -335,7 +335,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
throw new ImageFormatException($"Unsupported color mode. Max components 4; found {this.NumberOfComponents}"); throw new ImageFormatException($"Unsupported color mode. Max components 4; found {this.NumberOfComponents}");
} }
this.pixelArea = new PdfJsJpegPixelArea(image.Width, image.Height, this.NumberOfComponents); this.pixelArea = new PdfJsJpegPixelArea(this.configuration.MemoryManager, image.Width, image.Height, this.NumberOfComponents);
this.pixelArea.LinearizeBlockData(this.components, image.Width, image.Height); this.pixelArea.LinearizeBlockData(this.components, image.Width, image.Height);
if (this.NumberOfComponents == 1) if (this.NumberOfComponents == 1)
@ -648,7 +648,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
maxV = v; maxV = v;
} }
var component = new PdfJsFrameComponent(this.Frame, this.temp[index], h, v, this.temp[index + 2], i); var component = new PdfJsFrameComponent(this.configuration.MemoryManager, this.Frame, this.temp[index], h, v, this.temp[index + 2], i);
this.Frame.Components[i] = component; this.Frame.Components[i] = component;
this.Frame.ComponentIds[i] = component.Id; this.Frame.ComponentIds[i] = component.Id;
@ -673,14 +673,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
throw new ImageFormatException($"DHT has wrong length: {remaining}"); throw new ImageFormatException($"DHT has wrong length: {remaining}");
} }
using (var huffmanData = MemoryManager.Current.Allocate<byte>(256, true)) using (var huffmanData = this.configuration.MemoryManager.Allocate<byte>(256, true))
{ {
for (int i = 2; i < remaining;) for (int i = 2; i < remaining;)
{ {
byte huffmanTableSpec = (byte)this.InputStream.ReadByte(); byte huffmanTableSpec = (byte)this.InputStream.ReadByte();
this.InputStream.Read(huffmanData.Array, 0, 16); this.InputStream.Read(huffmanData.Array, 0, 16);
using (var codeLengths = MemoryManager.Current.Allocate<byte>(17, true)) using (var codeLengths = this.configuration.MemoryManager.Allocate<byte>(17, true))
{ {
int codeLengthSum = 0; int codeLengthSum = 0;
@ -689,7 +689,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
codeLengthSum += codeLengths[j] = huffmanData[j - 1]; codeLengthSum += codeLengths[j] = huffmanData[j - 1];
} }
using (var huffmanValues = MemoryManager.Current.Allocate<byte>(256, true)) using (var huffmanValues = this.configuration.MemoryManager.Allocate<byte>(256, true))
{ {
this.InputStream.Read(huffmanValues.Array, 0, codeLengthSum); this.InputStream.Read(huffmanValues.Array, 0, codeLengthSum);
@ -784,8 +784,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
{ {
int blocksPerLine = component.BlocksPerLine; int blocksPerLine = component.BlocksPerLine;
int blocksPerColumn = component.BlocksPerColumn; int blocksPerColumn = component.BlocksPerColumn;
using (var computationBuffer = MemoryManager.Current.Allocate<short>(64, true)) using (var computationBuffer = this.configuration.MemoryManager.Allocate<short>(64, true))
using (var multiplicationBuffer = MemoryManager.Current.Allocate<short>(64, true)) using (var multiplicationBuffer = this.configuration.MemoryManager.Allocate<short>(64, true))
{ {
Span<short> quantizationTable = this.quantizationTables.Tables.GetRowSpan(frameComponent.QuantizationTableIndex); Span<short> quantizationTable = this.quantizationTables.Tables.GetRowSpan(frameComponent.QuantizationTableIndex);
Span<short> computationBufferSpan = computationBuffer; Span<short> computationBufferSpan = computationBuffer;
@ -823,7 +823,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// <param name="values">The values</param> /// <param name="values">The values</param>
private void BuildHuffmanTable(PdfJsHuffmanTables tables, int index, byte[] codeLengths, byte[] values) private void BuildHuffmanTable(PdfJsHuffmanTables tables, int index, byte[] codeLengths, byte[] values)
{ {
tables[index] = new PdfJsHuffmanTable(codeLengths, values); tables[index] = new PdfJsHuffmanTable(this.configuration.MemoryManager, codeLengths, values);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

8
src/ImageSharp/Formats/Png/PngConfigurationModule.cs

@ -9,11 +9,11 @@ namespace SixLabors.ImageSharp.Formats.Png
public sealed class PngConfigurationModule : IConfigurationModule public sealed class PngConfigurationModule : IConfigurationModule
{ {
/// <inheritdoc/> /// <inheritdoc/>
public void Configure(Configuration host) public void Configure(Configuration config)
{ {
host.SetEncoder(ImageFormats.Png, new PngEncoder()); config.SetEncoder(ImageFormats.Png, new PngEncoder(config.MemoryManager));
host.SetDecoder(ImageFormats.Png, new PngDecoder()); config.SetDecoder(ImageFormats.Png, new PngDecoder());
host.AddImageFormatDetector(new PngImageFormatDetector()); config.AddImageFormatDetector(new PngImageFormatDetector());
} }
} }
} }

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

@ -375,8 +375,8 @@ namespace SixLabors.ImageSharp.Formats.Png
this.bytesPerSample = this.header.BitDepth / 8; this.bytesPerSample = this.header.BitDepth / 8;
} }
this.previousScanline = MemoryManager.Current.Allocate<byte>(this.bytesPerScanline, true); this.previousScanline = this.configuration.MemoryManager.Allocate<byte>(this.bytesPerScanline, true);
this.scanline = MemoryManager.Current.Allocate<byte>(this.bytesPerScanline, true); this.scanline = this.configuration.MemoryManager.Allocate<byte>(this.bytesPerScanline, true);
} }
/// <summary> /// <summary>
@ -669,7 +669,7 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.header.BitDepth == 16) if (this.header.BitDepth == 16)
{ {
int length = this.header.Width * 3; int length = this.header.Width * 3;
using (var compressed = MemoryManager.Current.Allocate<byte>(length)) using (var compressed = this.configuration.MemoryManager.Allocate<byte>(length))
{ {
// TODO: Should we use pack from vector here instead? // TODO: Should we use pack from vector here instead?
this.From16BitTo8Bit(scanlineBuffer, compressed, length); this.From16BitTo8Bit(scanlineBuffer, compressed, length);
@ -686,7 +686,7 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.header.BitDepth == 16) if (this.header.BitDepth == 16)
{ {
int length = this.header.Width * 3; int length = this.header.Width * 3;
using (var compressed = MemoryManager.Current.Allocate<byte>(length)) using (var compressed = this.configuration.MemoryManager.Allocate<byte>(length))
{ {
// TODO: Should we use pack from vector here instead? // TODO: Should we use pack from vector here instead?
this.From16BitTo8Bit(scanlineBuffer, compressed, length); this.From16BitTo8Bit(scanlineBuffer, compressed, length);
@ -727,7 +727,7 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.header.BitDepth == 16) if (this.header.BitDepth == 16)
{ {
int length = this.header.Width * 4; int length = this.header.Width * 4;
using (var compressed = MemoryManager.Current.Allocate<byte>(length)) using (var compressed = this.configuration.MemoryManager.Allocate<byte>(length))
{ {
// TODO: Should we use pack from vector here instead? // TODO: Should we use pack from vector here instead?
this.From16BitTo8Bit(scanlineBuffer, compressed, length); this.From16BitTo8Bit(scanlineBuffer, compressed, length);
@ -930,7 +930,7 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.header.BitDepth == 16) if (this.header.BitDepth == 16)
{ {
int length = this.header.Width * 3; int length = this.header.Width * 3;
using (var compressed = MemoryManager.Current.Allocate<byte>(length)) using (var compressed = this.configuration.MemoryManager.Allocate<byte>(length))
{ {
// TODO: Should we use pack from vector here instead? // TODO: Should we use pack from vector here instead?
this.From16BitTo8Bit(scanlineBuffer, compressed, length); this.From16BitTo8Bit(scanlineBuffer, compressed, length);
@ -998,7 +998,7 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.header.BitDepth == 16) if (this.header.BitDepth == 16)
{ {
int length = this.header.Width * 4; int length = this.header.Width * 4;
using (var compressed = MemoryManager.Current.Allocate<byte>(length)) using (var compressed = this.configuration.MemoryManager.Allocate<byte>(length))
{ {
// TODO: Should we use pack from vector here instead? // TODO: Should we use pack from vector here instead?
this.From16BitTo8Bit(scanlineBuffer, compressed, length); this.From16BitTo8Bit(scanlineBuffer, compressed, length);

11
src/ImageSharp/Formats/Png/PngEncoder.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System.IO; using System.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Quantizers; using SixLabors.ImageSharp.Quantizers;
@ -12,6 +14,13 @@ namespace SixLabors.ImageSharp.Formats.Png
/// </summary> /// </summary>
public sealed class PngEncoder : IImageEncoder, IPngEncoderOptions public sealed class PngEncoder : IImageEncoder, IPngEncoderOptions
{ {
private readonly MemoryManager memoryManager;
public PngEncoder(MemoryManager memoryManager)
{
this.memoryManager = memoryManager;
}
/// <summary> /// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being encoded. /// Gets or sets a value indicating whether the metadata should be ignored when the image is being encoded.
/// </summary> /// </summary>
@ -66,7 +75,7 @@ namespace SixLabors.ImageSharp.Formats.Png
public void Encode<TPixel>(Image<TPixel> image, Stream stream) public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
using (var encoder = new PngEncoderCore(this)) using (var encoder = new PngEncoderCore(this.memoryManager, this))
{ {
encoder.Encode(image, stream); encoder.Encode(image, stream);
} }

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

@ -20,6 +20,8 @@ namespace SixLabors.ImageSharp.Formats.Png
/// </summary> /// </summary>
internal sealed class PngEncoderCore : IDisposable internal sealed class PngEncoderCore : IDisposable
{ {
private readonly MemoryManager memoryManager;
/// <summary> /// <summary>
/// The maximum block size, defaults at 64k for uncompressed blocks. /// The maximum block size, defaults at 64k for uncompressed blocks.
/// </summary> /// </summary>
@ -149,8 +151,9 @@ namespace SixLabors.ImageSharp.Formats.Png
/// Initializes a new instance of the <see cref="PngEncoderCore"/> class. /// Initializes a new instance of the <see cref="PngEncoderCore"/> class.
/// </summary> /// </summary>
/// <param name="options">The options for influancing the encoder</param> /// <param name="options">The options for influancing the encoder</param>
public PngEncoderCore(IPngEncoderOptions options) public PngEncoderCore(MemoryManager memoryManager, IPngEncoderOptions options)
{ {
this.memoryManager = memoryManager;
this.ignoreMetadata = options.IgnoreMetadata; this.ignoreMetadata = options.IgnoreMetadata;
this.paletteSize = options.PaletteSize > 0 ? options.PaletteSize.Clamp(1, int.MaxValue) : int.MaxValue; this.paletteSize = options.PaletteSize > 0 ? options.PaletteSize.Clamp(1, int.MaxValue) : int.MaxValue;
this.pngColorType = options.PngColorType; this.pngColorType = options.PngColorType;
@ -620,16 +623,16 @@ namespace SixLabors.ImageSharp.Formats.Png
this.bytesPerScanline = this.width * this.bytesPerPixel; this.bytesPerScanline = this.width * this.bytesPerPixel;
int resultLength = this.bytesPerScanline + 1; int resultLength = this.bytesPerScanline + 1;
this.previousScanline = MemoryManager.Current.Allocate<byte>(this.bytesPerScanline, true); this.previousScanline = this.memoryManager.Allocate<byte>(this.bytesPerScanline, true);
this.rawScanline = MemoryManager.Current.Allocate<byte>(this.bytesPerScanline, true); this.rawScanline = this.memoryManager.Allocate<byte>(this.bytesPerScanline, true);
this.result = MemoryManager.Current.Allocate<byte>(resultLength, true); this.result = this.memoryManager.Allocate<byte>(resultLength, true);
if (this.pngColorType != PngColorType.Palette) if (this.pngColorType != PngColorType.Palette)
{ {
this.sub = MemoryManager.Current.Allocate<byte>(resultLength, true); this.sub = this.memoryManager.Allocate<byte>(resultLength, true);
this.up = MemoryManager.Current.Allocate<byte>(resultLength, true); this.up = this.memoryManager.Allocate<byte>(resultLength, true);
this.average = MemoryManager.Current.Allocate<byte>(resultLength, true); this.average = this.memoryManager.Allocate<byte>(resultLength, true);
this.paeth = MemoryManager.Current.Allocate<byte>(resultLength, true); this.paeth = this.memoryManager.Allocate<byte>(resultLength, true);
} }
byte[] buffer; byte[] buffer;

3
src/ImageSharp/IImageProcessingContext{TPixel}.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -28,6 +29,8 @@ namespace SixLabors.ImageSharp
/// <param name="processor">The processor to apply</param> /// <param name="processor">The processor to apply</param>
/// <returns>The current operations class to allow chaining of operations.</returns> /// <returns>The current operations class to allow chaining of operations.</returns>
IImageProcessingContext<TPixel> ApplyProcessor(IImageProcessor<TPixel> processor); IImageProcessingContext<TPixel> ApplyProcessor(IImageProcessor<TPixel> processor);
MemoryManager GetMemoryManager();
} }
/// <summary> /// <summary>

2
src/ImageSharp/Image/Image.Decode.cs

@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp
return null; return null;
} }
using (var buffer = MemoryManager.Current.Allocate<byte>(maxHeaderSize)) using (var buffer = config.MemoryManager.Allocate<byte>(maxHeaderSize))
{ {
long startPosition = stream.Position; long startPosition = stream.Position;
stream.Read(buffer.Array, 0, maxHeaderSize); stream.Read(buffer.Array, 0, maxHeaderSize);

2
src/ImageSharp/Image/ImageFrame.LoadPixelData.cs

@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp
int count = width * height; int count = width * height;
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data));
var image = new ImageFrame<TPixel>(width, height); var image = new ImageFrame<TPixel>(Configuration.Default.MemoryManager, width, height);
SpanHelper.Copy(data, image.GetPixelSpan(), count); SpanHelper.Copy(data, image.GetPixelSpan(), count);
return image; return image;

4
src/ImageSharp/Image/ImageFrameCollection.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp
this.parent = parent; this.parent = parent;
// Frames are already cloned within the caller // Frames are already cloned within the caller
this.frames.Add(new ImageFrame<TPixel>(width, height)); this.frames.Add(new ImageFrame<TPixel>(parent.GetConfiguration().MemoryManager, width, height));
} }
internal ImageFrameCollection(Image<TPixel> parent, IEnumerable<ImageFrame<TPixel>> frames) internal ImageFrameCollection(Image<TPixel> parent, IEnumerable<ImageFrame<TPixel>> frames)
@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp
/// <inheritdoc/> /// <inheritdoc/>
public ImageFrame<TPixel> CreateFrame() public ImageFrame<TPixel> CreateFrame()
{ {
var frame = new ImageFrame<TPixel>(this.RootFrame.Width, this.RootFrame.Height); var frame = new ImageFrame<TPixel>(this.parent.GetConfiguration().MemoryManager, this.RootFrame.Width, this.RootFrame.Height);
this.frames.Add(frame); this.frames.Add(frame);
return frame; return frame;
} }

21
src/ImageSharp/Image/ImageFrame{TPixel}.cs

@ -20,6 +20,8 @@ namespace SixLabors.ImageSharp
public sealed class ImageFrame<TPixel> : IPixelSource<TPixel>, IDisposable public sealed class ImageFrame<TPixel> : IPixelSource<TPixel>, IDisposable
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
public MemoryManager MemoryManager { get; }
/// <summary> /// <summary>
/// The image pixels. Not private as Buffer2D requires an array in its constructor. /// The image pixels. Not private as Buffer2D requires an array in its constructor.
/// </summary> /// </summary>
@ -32,8 +34,8 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
/// <param name="width">The width of the image in pixels.</param> /// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param>
internal ImageFrame(int width, int height) internal ImageFrame(MemoryManager memoryManager, int width, int height)
: this(width, height, new ImageFrameMetaData()) : this(memoryManager, width, height, new ImageFrameMetaData())
{ {
} }
@ -43,13 +45,15 @@ namespace SixLabors.ImageSharp
/// <param name="width">The width of the image in pixels.</param> /// <param name="width">The width of the image in pixels.</param>
/// <param name="height">The height of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param>
/// <param name="metaData">The meta data.</param> /// <param name="metaData">The meta data.</param>
internal ImageFrame(int width, int height, ImageFrameMetaData metaData) internal ImageFrame(MemoryManager memoryManager, int width, int height, ImageFrameMetaData metaData)
{ {
Guard.NotNull(memoryManager, nameof(memoryManager));
Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.MustBeGreaterThan(height, 0, nameof(height));
Guard.NotNull(metaData, nameof(metaData)); Guard.NotNull(metaData, nameof(metaData));
this.pixelBuffer = Buffer2D<TPixel>.CreateClean(width, height); this.MemoryManager = memoryManager;
this.pixelBuffer = memoryManager.Allocate2D<TPixel>(width, height, true);
this.MetaData = metaData; this.MetaData = metaData;
} }
@ -57,9 +61,10 @@ namespace SixLabors.ImageSharp
/// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class.
/// </summary> /// </summary>
/// <param name="source">The source.</param> /// <param name="source">The source.</param>
internal ImageFrame(ImageFrame<TPixel> source) internal ImageFrame(MemoryManager memoryManager, ImageFrame<TPixel> source)
{ {
this.pixelBuffer = MemoryManager.Current.Allocate2D<TPixel>(source.pixelBuffer.Width, source.pixelBuffer.Height); this.MemoryManager = memoryManager;
this.pixelBuffer = memoryManager.Allocate2D<TPixel>(source.pixelBuffer.Width, source.pixelBuffer.Height);
source.pixelBuffer.Span.CopyTo(this.pixelBuffer.Span); source.pixelBuffer.Span.CopyTo(this.pixelBuffer.Span);
this.MetaData = source.MetaData.Clone(); this.MetaData = source.MetaData.Clone();
} }
@ -198,7 +203,7 @@ namespace SixLabors.ImageSharp
Func<Vector4, Vector4> scaleFunc = PackedPixelConverterHelper.ComputeScaleFunction<TPixel, TPixel2>(); Func<Vector4, Vector4> scaleFunc = PackedPixelConverterHelper.ComputeScaleFunction<TPixel, TPixel2>();
var target = new ImageFrame<TPixel2>(this.Width, this.Height, this.MetaData.Clone()); var target = new ImageFrame<TPixel2>(this.MemoryManager, this.Width, this.Height, this.MetaData.Clone());
using (PixelAccessor<TPixel> pixels = this.Lock()) using (PixelAccessor<TPixel> pixels = this.Lock())
using (PixelAccessor<TPixel2> targetPixels = target.Lock()) using (PixelAccessor<TPixel2> targetPixels = target.Lock())
@ -227,7 +232,7 @@ namespace SixLabors.ImageSharp
/// <returns>The <see cref="ImageFrame{TPixel}"/></returns> /// <returns>The <see cref="ImageFrame{TPixel}"/></returns>
internal ImageFrame<TPixel> Clone() internal ImageFrame<TPixel> Clone()
{ {
return new ImageFrame<TPixel>(this); return new ImageFrame<TPixel>(this.MemoryManager, this);
} }
/// <inheritdoc/> /// <inheritdoc/>

2
src/ImageSharp/Image/PixelAccessor{TPixel}.cs

@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp
/// <param name="width">The width of the image represented by the pixel buffer.</param> /// <param name="width">The width of the image represented by the pixel buffer.</param>
/// <param name="height">The height of the image represented by the pixel buffer.</param> /// <param name="height">The height of the image represented by the pixel buffer.</param>
public PixelAccessor(int width, int height) public PixelAccessor(int width, int height)
: this(width, height, Buffer2D<TPixel>.CreateClean(width, height), true) : this(width, height, Configuration.Default.MemoryManager.Allocate2D<TPixel>(width, height, true), true)
{ {
} }

2
src/ImageSharp/Image/PixelArea{TPixel}.cs

@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp
this.RowStride = (width * GetComponentCount(componentOrder)) + padding; this.RowStride = (width * GetComponentCount(componentOrder)) + padding;
this.Length = this.RowStride * height; this.Length = this.RowStride * height;
this.byteBuffer = MemoryManager.Current.Allocate<byte>(this.Length, true); this.byteBuffer = Configuration.Default.MemoryManager.Allocate<byte>(this.Length, true);
} }
/// <summary> /// <summary>

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

@ -56,24 +56,6 @@ namespace SixLabors.ImageSharp.Memory
} }
} }
/// <summary>
/// Creates a clean instance of <see cref="Buffer2D{T}"/> initializing it's elements with 'default(T)'.
/// </summary>
/// <param name="width">The number of elements in a row</param>
/// <param name="height">The number of rows</param>
/// <returns>The <see cref="Buffer{T}"/> instance</returns>
public static Buffer2D<T> CreateClean(int width, int height)
{
return new Buffer2D<T>(MemoryManager.Current.Allocate<T>(width * height, true), width, height);
}
/// <summary>
/// Creates a clean instance of <see cref="Buffer2D{T}"/> initializing it's elements with 'default(T)'.
/// </summary>
/// <param name="size">The size of the buffer</param>
/// <returns>The <see cref="Buffer2D{T}"/> instance</returns>
public static Buffer2D<T> CreateClean(Size size) => CreateClean(size.Width, size.Height);
public void Dispose() public void Dispose()
{ {
this.Buffer?.Dispose(); this.Buffer?.Dispose();

5
src/ImageSharp/Memory/MemoryManager.cs

@ -11,11 +11,6 @@ namespace SixLabors.ImageSharp.Memory
/// </summary> /// </summary>
public abstract class MemoryManager public abstract class MemoryManager
{ {
/// <summary>
/// Gets or sets the <see cref="MemoryManager"/> that is currently in use.
/// </summary>
public static MemoryManager Current { get; set; } = new ArrayPoolMemoryManager(1024 * 80);
/// <summary> /// <summary>
/// Allocates a <see cref="Buffer{T}"/> of size <paramref name="size"/>, optionally /// Allocates a <see cref="Buffer{T}"/> of size <paramref name="size"/>, optionally
/// clearing the buffer before it gets returned. /// clearing the buffer before it gets returned.

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

@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -201,7 +201,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -240,7 +240,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -279,7 +279,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -318,7 +318,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -357,7 +357,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -396,7 +396,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -435,7 +435,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -474,7 +474,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -513,7 +513,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -552,7 +552,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -591,7 +591,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -630,7 +630,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -669,7 +669,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -708,7 +708,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -747,7 +747,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -786,7 +786,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -825,7 +825,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);

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

@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (Buffer<Vector4> buffer = MemoryManager.Current.Allocate<Vector4>(destination.Length * 3)) using (Buffer<Vector4> buffer = Configuration.Default.MemoryManager.Allocate<Vector4>(destination.Length * 3))
{ {
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);

4
src/ImageSharp/Processing/ColorMatrix/Lomograph.cs

@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp
public static IImageProcessingContext<TPixel> Lomograph<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options) public static IImageProcessingContext<TPixel> Lomograph<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
source.ApplyProcessor(new LomographProcessor<TPixel>(options)); source.ApplyProcessor(new LomographProcessor<TPixel>(source.GetMemoryManager(), options));
return source; return source;
} }
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp
public static IImageProcessingContext<TPixel> Lomograph<TPixel>(this IImageProcessingContext<TPixel> source, Rectangle rectangle, GraphicsOptions options) public static IImageProcessingContext<TPixel> Lomograph<TPixel>(this IImageProcessingContext<TPixel> source, Rectangle rectangle, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
source.ApplyProcessor(new LomographProcessor<TPixel>(options), rectangle); source.ApplyProcessor(new LomographProcessor<TPixel>(source.GetMemoryManager(), options), rectangle);
return source; return source;
} }
} }

4
src/ImageSharp/Processing/ColorMatrix/Polaroid.cs

@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp
public static IImageProcessingContext<TPixel> Polaroid<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options) public static IImageProcessingContext<TPixel> Polaroid<TPixel>(this IImageProcessingContext<TPixel> source, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
source.ApplyProcessor(new PolaroidProcessor<TPixel>(options)); source.ApplyProcessor(new PolaroidProcessor<TPixel>(source.GetMemoryManager(), options));
return source; return source;
} }
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp
public static IImageProcessingContext<TPixel> Polaroid<TPixel>(this IImageProcessingContext<TPixel> source, Rectangle rectangle, GraphicsOptions options) public static IImageProcessingContext<TPixel> Polaroid<TPixel>(this IImageProcessingContext<TPixel> source, Rectangle rectangle, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
source.ApplyProcessor(new PolaroidProcessor<TPixel>(options), rectangle); source.ApplyProcessor(new PolaroidProcessor<TPixel>(source.GetMemoryManager(), options), rectangle);
return source; return source;
} }
} }

4
src/ImageSharp/Processing/Effects/BackgroundColor.cs

@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static IImageProcessingContext<TPixel> BackgroundColor<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, GraphicsOptions options) public static IImageProcessingContext<TPixel> BackgroundColor<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
=> source.ApplyProcessor(new BackgroundColorProcessor<TPixel>(color, options)); => source.ApplyProcessor(new BackgroundColorProcessor<TPixel>(source.GetMemoryManager(), color, options));
/// <summary> /// <summary>
/// Replaces the background color of image with the given one. /// Replaces the background color of image with the given one.
@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="Image{TPixel}"/>.</returns>
public static IImageProcessingContext<TPixel> BackgroundColor<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, Rectangle rectangle, GraphicsOptions options) public static IImageProcessingContext<TPixel> BackgroundColor<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, Rectangle rectangle, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
=> source.ApplyProcessor(new BackgroundColorProcessor<TPixel>(color, options), rectangle); => source.ApplyProcessor(new BackgroundColorProcessor<TPixel>(source.GetMemoryManager(), color, options), rectangle);
/// <summary> /// <summary>
/// Replaces the background color of image with the given one. /// Replaces the background color of image with the given one.

4
src/ImageSharp/Processing/Overlays/Glow.cs

@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="Image{TPixel}"/>.</returns>
private static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, ValueSize radius, Rectangle rectangle, GraphicsOptions options) private static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, ValueSize radius, Rectangle rectangle, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
=> source.ApplyProcessor(new GlowProcessor<TPixel>(color, radius, options), rectangle); => source.ApplyProcessor(new GlowProcessor<TPixel>(source.GetMemoryManager(), color, radius, options), rectangle);
/// <summary> /// <summary>
/// Applies a radial glow effect to an image. /// Applies a radial glow effect to an image.
@ -170,6 +170,6 @@ namespace SixLabors.ImageSharp
/// <returns>The <see cref="Image{TPixel}"/>.</returns> /// <returns>The <see cref="Image{TPixel}"/>.</returns>
private static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, ValueSize radius, GraphicsOptions options) private static IImageProcessingContext<TPixel> Glow<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, ValueSize radius, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
=> source.ApplyProcessor(new GlowProcessor<TPixel>(color, radius, options)); => source.ApplyProcessor(new GlowProcessor<TPixel>(source.GetMemoryManager(), color, radius, options));
} }
} }

4
src/ImageSharp/Processing/Overlays/Vignette.cs

@ -151,10 +151,10 @@ namespace SixLabors.ImageSharp
private static IImageProcessingContext<TPixel> VignetteInternal<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, ValueSize radiusX, ValueSize radiusY, Rectangle rectangle, GraphicsOptions options) private static IImageProcessingContext<TPixel> VignetteInternal<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, ValueSize radiusX, ValueSize radiusY, Rectangle rectangle, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
=> source.ApplyProcessor(new VignetteProcessor<TPixel>(color, radiusX, radiusY, options), rectangle); => source.ApplyProcessor(new VignetteProcessor<TPixel>(source.GetMemoryManager(), color, radiusX, radiusY, options), rectangle);
private static IImageProcessingContext<TPixel> VignetteInternal<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options) private static IImageProcessingContext<TPixel> VignetteInternal<TPixel>(this IImageProcessingContext<TPixel> source, TPixel color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
=> source.ApplyProcessor(new VignetteProcessor<TPixel>(color, radiusX, radiusY, options)); => source.ApplyProcessor(new VignetteProcessor<TPixel>(source.GetMemoryManager(), color, radiusX, radiusY, options));
} }
} }

11
src/ImageSharp/Processing/Processors/ColorMatrix/LomographProcessor.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -15,14 +17,17 @@ namespace SixLabors.ImageSharp.Processing.Processors
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private static readonly TPixel VeryDarkGreen = ColorBuilder<TPixel>.FromRGBA(0, 10, 0, 255); private static readonly TPixel VeryDarkGreen = ColorBuilder<TPixel>.FromRGBA(0, 10, 0, 255);
private readonly MemoryManager memoryManager;
private readonly GraphicsOptions options; private readonly GraphicsOptions options;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LomographProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="LomographProcessor{TPixel}" /> class.
/// </summary> /// </summary>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="options">The options effecting blending and composition.</param>
public LomographProcessor(GraphicsOptions options) public LomographProcessor(MemoryManager memoryManager, GraphicsOptions options) {
{ this.memoryManager = memoryManager;
this.options = options; this.options = options;
} }
@ -41,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <inheritdoc/> /// <inheritdoc/>
protected override void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) protected override void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{ {
new VignetteProcessor<TPixel>(VeryDarkGreen, this.options).Apply(source, sourceRectangle, configuration); new VignetteProcessor<TPixel>(this.memoryManager, VeryDarkGreen, this.options).Apply(source, sourceRectangle, configuration);
} }
} }
} }

13
src/ImageSharp/Processing/Processors/ColorMatrix/PolaroidProcessor.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System.Numerics; using System.Numerics;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -16,14 +18,17 @@ namespace SixLabors.ImageSharp.Processing.Processors
{ {
private static readonly TPixel VeryDarkOrange = ColorBuilder<TPixel>.FromRGB(102, 34, 0); private static readonly TPixel VeryDarkOrange = ColorBuilder<TPixel>.FromRGB(102, 34, 0);
private static readonly TPixel LightOrange = ColorBuilder<TPixel>.FromRGBA(255, 153, 102, 178); private static readonly TPixel LightOrange = ColorBuilder<TPixel>.FromRGBA(255, 153, 102, 178);
private readonly MemoryManager memoryManager;
private readonly GraphicsOptions options; private readonly GraphicsOptions options;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="PolaroidProcessor{TPixel}" /> class. /// Initializes a new instance of the <see cref="PolaroidProcessor{TPixel}" /> class.
/// </summary> /// </summary>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="options">The options effecting blending and composition.</param>
public PolaroidProcessor(GraphicsOptions options) public PolaroidProcessor(MemoryManager memoryManager, GraphicsOptions options) {
{ this.memoryManager = memoryManager;
this.options = options; this.options = options;
} }
@ -48,8 +53,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <inheritdoc/> /// <inheritdoc/>
protected override void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) protected override void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{ {
new VignetteProcessor<TPixel>(VeryDarkOrange, this.options).Apply(source, sourceRectangle, configuration); new VignetteProcessor<TPixel>(this.memoryManager, VeryDarkOrange, this.options).Apply(source, sourceRectangle, configuration);
new GlowProcessor<TPixel>(LightOrange, source.Width / 4F, this.options).Apply(source, sourceRectangle, configuration); new GlowProcessor<TPixel>(this.memoryManager, LightOrange, source.Width / 4F, this.options).Apply(source, sourceRectangle, configuration);
} }
} }
} }

9
src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs

@ -17,6 +17,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
internal class BackgroundColorProcessor<TPixel> : ImageProcessor<TPixel> internal class BackgroundColorProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private readonly MemoryManager memoryManager;
private readonly GraphicsOptions options; private readonly GraphicsOptions options;
/// <summary> /// <summary>
@ -24,9 +26,10 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// </summary> /// </summary>
/// <param name="color">The <typeparamref name="TPixel"/> to set the background color to.</param> /// <param name="color">The <typeparamref name="TPixel"/> to set the background color to.</param>
/// <param name="options">The options defining blending algorithum and amount.</param> /// <param name="options">The options defining blending algorithum and amount.</param>
public BackgroundColorProcessor(TPixel color, GraphicsOptions options) public BackgroundColorProcessor(MemoryManager memoryManager, TPixel color, GraphicsOptions options)
{ {
this.Value = color; this.Value = color;
this.memoryManager = memoryManager;
this.options = options; this.options = options;
} }
@ -67,8 +70,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
int width = maxX - minX; int width = maxX - minX;
using (var colors = MemoryManager.Current.Allocate<TPixel>(width)) using (var colors = this.memoryManager.Allocate<TPixel>(width))
using (var amount = MemoryManager.Current.Allocate<float>(width)) using (var amount = this.memoryManager.Allocate<float>(width))
{ {
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
{ {

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

@ -19,6 +19,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
internal class GlowProcessor<TPixel> : ImageProcessor<TPixel> internal class GlowProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private readonly MemoryManager memoryManager;
private readonly GraphicsOptions options; private readonly GraphicsOptions options;
private readonly PixelBlender<TPixel> blender; private readonly PixelBlender<TPixel> blender;
@ -28,8 +30,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <param name="color">The color or the glow.</param> /// <param name="color">The color or the glow.</param>
/// <param name="radius">The radius of the glow.</param> /// <param name="radius">The radius of the glow.</param>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="options">The options effecting blending and composition.</param>
public GlowProcessor(TPixel color, ValueSize radius, GraphicsOptions options) public GlowProcessor(MemoryManager memoryManager, TPixel color, ValueSize radius, GraphicsOptions options)
{ {
this.memoryManager = memoryManager;
this.options = options; this.options = options;
this.GlowColor = color; this.GlowColor = color;
this.Radius = radius; this.Radius = radius;
@ -83,7 +86,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
} }
int width = maxX - minX; int width = maxX - minX;
using (var rowColors = MemoryManager.Current.Allocate<TPixel>(width)) using (var rowColors = this.memoryManager.Allocate<TPixel>(width))
{ {
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
{ {
@ -96,7 +99,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
configuration.ParallelOptions, configuration.ParallelOptions,
y => y =>
{ {
using (var amounts = MemoryManager.Current.Allocate<float>(width)) using (var amounts = this.memoryManager.Allocate<float>(width))
{ {
int offsetY = y - startY; int offsetY = y - startY;
int offsetX = minX - startX; int offsetX = minX - startX;

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

@ -19,6 +19,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
internal class VignetteProcessor<TPixel> : ImageProcessor<TPixel> internal class VignetteProcessor<TPixel> : ImageProcessor<TPixel>
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private readonly MemoryManager memoryManager;
private readonly GraphicsOptions options; private readonly GraphicsOptions options;
private readonly PixelBlender<TPixel> blender; private readonly PixelBlender<TPixel> blender;
@ -29,11 +31,12 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <param name="radiusX">The x-radius.</param> /// <param name="radiusX">The x-radius.</param>
/// <param name="radiusY">The y-radius.</param> /// <param name="radiusY">The y-radius.</param>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="options">The options effecting blending and composition.</param>
public VignetteProcessor(TPixel color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options) public VignetteProcessor(MemoryManager memoryManager, TPixel color, ValueSize radiusX, ValueSize radiusY, GraphicsOptions options)
{ {
this.VignetteColor = color; this.VignetteColor = color;
this.RadiusX = radiusX; this.RadiusX = radiusX;
this.RadiusY = radiusY; this.RadiusY = radiusY;
this.memoryManager = memoryManager;
this.options = options; this.options = options;
this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.options.BlenderMode); this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.options.BlenderMode);
} }
@ -43,9 +46,10 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// </summary> /// </summary>
/// <param name="color">The color of the vignette.</param> /// <param name="color">The color of the vignette.</param>
/// <param name="options">The options effecting blending and composition.</param> /// <param name="options">The options effecting blending and composition.</param>
public VignetteProcessor(TPixel color, GraphicsOptions options) public VignetteProcessor(MemoryManager memoryManager, TPixel color, GraphicsOptions options)
{ {
this.VignetteColor = color; this.VignetteColor = color;
this.memoryManager = memoryManager;
this.options = options; this.options = options;
this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.options.BlenderMode); this.blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.options.BlenderMode);
} }
@ -104,7 +108,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
} }
int width = maxX - minX; int width = maxX - minX;
using (var rowColors = MemoryManager.Current.Allocate<TPixel>(width)) using (var rowColors = this.memoryManager.Allocate<TPixel>(width))
{ {
for (int i = 0; i < width; i++) for (int i = 0; i < width; i++)
{ {
@ -117,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
configuration.ParallelOptions, configuration.ParallelOptions,
y => y =>
{ {
using (var amounts = MemoryManager.Current.Allocate<float>(width)) using (var amounts = this.memoryManager.Allocate<float>(width))
{ {
int offsetY = y - startY; int offsetY = y - startY;
int offsetX = minX - startX; int offsetX = minX - startX;

4
src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs

@ -164,9 +164,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// </summary> /// </summary>
/// <param name="sourceSize">The size of the source window</param> /// <param name="sourceSize">The size of the source window</param>
/// <param name="destinationSize">The size of the destination window</param> /// <param name="destinationSize">The size of the destination window</param>
public WeightsBuffer(int sourceSize, int destinationSize) public WeightsBuffer(MemoryManager memoryManager, int sourceSize, int destinationSize)
{ {
this.dataBuffer = Buffer2D<float>.CreateClean(sourceSize, destinationSize); this.dataBuffer = memoryManager.Allocate2D<float>(sourceSize, destinationSize, true);
this.Weights = new WeightsWindow[destinationSize]; this.Weights = new WeightsWindow[destinationSize];
} }

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

@ -3,6 +3,8 @@
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -25,18 +27,20 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <param name="resizeRectangle"> /// <param name="resizeRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the target image object to draw to. /// The <see cref="Rectangle"/> structure that specifies the portion of the target image object to draw to.
/// </param> /// </param>
protected ResamplingWeightedProcessor(IResampler sampler, int width, int height, Rectangle resizeRectangle) protected ResamplingWeightedProcessor(MemoryManager memoryManager, IResampler sampler, int width, int height, Rectangle resizeRectangle)
{ {
Guard.NotNull(memoryManager, nameof(memoryManager));
Guard.NotNull(sampler, nameof(sampler)); Guard.NotNull(sampler, nameof(sampler));
Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.MustBeGreaterThan(height, 0, nameof(height));
this.MemoryManager = memoryManager;
this.Sampler = sampler; this.Sampler = sampler;
this.Width = width; this.Width = width;
this.Height = height; this.Height = height;
this.ResizeRectangle = resizeRectangle; this.ResizeRectangle = resizeRectangle;
} }
/// <summary> /// <summary>
/// Gets the sampler to perform the resize operation. /// Gets the sampler to perform the resize operation.
/// </summary> /// </summary>
@ -56,6 +60,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// Gets or sets the resize rectangle. /// Gets or sets the resize rectangle.
/// </summary> /// </summary>
public Rectangle ResizeRectangle { get; protected set; } public Rectangle ResizeRectangle { get; protected set; }
protected MemoryManager MemoryManager { get; }
/// <summary> /// <summary>
/// Gets or sets the horizontal weights. /// Gets or sets the horizontal weights.
@ -86,7 +92,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
IResampler sampler = this.Sampler; IResampler sampler = this.Sampler;
float radius = MathF.Ceiling(scale * sampler.Radius); float radius = MathF.Ceiling(scale * sampler.Radius);
var result = new WeightsBuffer(sourceSize, destinationSize); var result = new WeightsBuffer(this.MemoryManager, sourceSize, destinationSize);
for (int i = 0; i < destinationSize; i++) for (int i = 0; i < destinationSize; i++)
{ {

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

@ -26,8 +26,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <param name="sampler">The sampler to perform the resize operation.</param> /// <param name="sampler">The sampler to perform the resize operation.</param>
/// <param name="width">The target width.</param> /// <param name="width">The target width.</param>
/// <param name="height">The target height.</param> /// <param name="height">The target height.</param>
public ResizeProcessor(IResampler sampler, int width, int height) public ResizeProcessor(MemoryManager memoryManager, IResampler sampler, int width, int height)
: base(sampler, width, height, new Rectangle(0, 0, width, height)) : base(memoryManager, sampler, width, height, new Rectangle(0, 0, width, height))
{ {
} }
@ -40,8 +40,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <param name="resizeRectangle"> /// <param name="resizeRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the target image object to draw to. /// The <see cref="Rectangle"/> structure that specifies the portion of the target image object to draw to.
/// </param> /// </param>
public ResizeProcessor(IResampler sampler, int width, int height, Rectangle resizeRectangle) public ResizeProcessor(MemoryManager memoryManager, IResampler sampler, int width, int height, Rectangle resizeRectangle)
: base(sampler, width, height, resizeRectangle) : base(memoryManager, sampler, width, height, resizeRectangle)
{ {
} }
@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
// ------------ // ------------
// For resize we know we are going to populate every pixel with fresh data and we want a different target size so // For resize we know we are going to populate every pixel with fresh data and we want a different target size so
// let's manually clone an empty set of images at the correct target and then have the base class process them in turn. // let's manually clone an empty set of images at the correct target and then have the base class process them in turn.
IEnumerable<ImageFrame<TPixel>> frames = source.Frames.Select(x => new ImageFrame<TPixel>(this.Width, this.Height, x.MetaData.Clone())); // this will create places holders IEnumerable<ImageFrame<TPixel>> frames = source.Frames.Select(x => new ImageFrame<TPixel>(source.GetConfiguration().MemoryManager, this.Width, this.Height, x.MetaData.Clone())); // this will create places holders
var image = new Image<TPixel>(config, source.MetaData.Clone(), frames); // base the place holder images in to prevent a extra frame being added var image = new Image<TPixel>(config, source.MetaData.Clone(), frames); // base the place holder images in to prevent a extra frame being added
return image; return image;
@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
// First process the columns. Since we are not using multiple threads startY and endY // First process the columns. Since we are not using multiple threads startY and endY
// are the upper and lower bounds of the source rectangle. // are the upper and lower bounds of the source rectangle.
// TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed! // TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed!
using (var firstPassPixels = MemoryManager.Current.Allocate2D<Vector4>(width, source.Height)) using (var firstPassPixels = this.MemoryManager.Allocate2D<Vector4>(width, source.Height))
{ {
firstPassPixels.Buffer.Clear(); firstPassPixels.Buffer.Clear();
@ -132,7 +132,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
y => y =>
{ {
// TODO: Without Parallel.For() this buffer object could be reused: // TODO: Without Parallel.For() this buffer object could be reused:
using (var tempRowBuffer = MemoryManager.Current.Allocate<Vector4>(source.Width)) using (var tempRowBuffer = this.MemoryManager.Allocate<Vector4>(source.Width))
{ {
Span<Vector4> firstPassRow = firstPassPixels.GetRowSpan(y); Span<Vector4> firstPassRow = firstPassPixels.GetRowSpan(y);
Span<TPixel> sourceRow = source.GetPixelRowSpan(y); Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

4
src/ImageSharp/Processing/Transforms/Resize.cs

@ -193,7 +193,7 @@ namespace SixLabors.ImageSharp
Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.MustBeGreaterThan(height, 0, nameof(height));
img.Mutate(x => x.ApplyProcessor(new ResizeProcessor<TPixel>(sampler, width, height, targetRectangle) { Compand = compand }, sourceRectangle)); img.Mutate(x => x.ApplyProcessor(new ResizeProcessor<TPixel>(source.GetMemoryManager(), sampler, width, height, targetRectangle) { Compand = compand }, sourceRectangle));
}); });
} }
@ -233,7 +233,7 @@ namespace SixLabors.ImageSharp
Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.MustBeGreaterThan(height, 0, nameof(height));
img.Mutate(x => x.ApplyProcessor(new ResizeProcessor<TPixel>(sampler, width, height, targetRectangle) { Compand = compand })); img.Mutate(x => x.ApplyProcessor(new ResizeProcessor<TPixel>(source.GetMemoryManager(), sampler, width, height, targetRectangle) { Compand = compand }));
}); });
} }
} }

6
tests/ImageSharp.Tests/FakeImageOperationsProvider.cs

@ -5,6 +5,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives; using SixLabors.Primitives;
@ -84,6 +87,9 @@ namespace SixLabors.ImageSharp.Tests
}); });
return this; return this;
} }
public MemoryManager GetMemoryManager() => this.source.GetConfiguration().MemoryManager;
public struct AppliedOpperation public struct AppliedOpperation
{ {
public Rectangle? Rectangle { get; set; } public Rectangle? Rectangle { get; set; }

Loading…
Cancel
Save