diff --git a/.travis.yml b/.travis.yml
index 70501a484b..54e4dee2f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,7 +6,7 @@ matrix:
- os: linux # Ubuntu 14.04
dist: trusty
sudo: required
- dotnet: 1.0.4
+ dotnet: 2.1.4
mono: latest
# - os: osx # OSX 10.11
# osx_image: xcode7.3.1
@@ -21,7 +21,7 @@ branches:
script:
- git submodule -q update --init
- dotnet restore
- - dotnet test tests/ImageSharp.Tests/ImageSharp.Tests.csproj -c Release -f "netcoreapp1.1"
+ - dotnet test tests/ImageSharp.Tests/ImageSharp.Tests.csproj -c Release -f "netcoreapp2.0"
env:
global:
diff --git a/.vscode/launch.json b/.vscode/launch.json
index c9c7453f64..c772e647ce 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceRoot}/samples/AvatarWithRoundedCorner/bin/Debug/netcoreapp1.1/AvatarWithRoundedCorner.dll",
+ "program": "${workspaceRoot}/tests/ImageSharp.Benchmarks/bin/Debug/netcoreapp2.0/ImageSharp.Benchmarks.dll",
"args": [],
"cwd": "${workspaceRoot}/samples/AvatarWithRoundedCorner",
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 4a7b35ac2c..82aaa2f8d0 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -16,13 +16,13 @@
{
"taskName": "build benchmark",
"suppressTaskName": true,
- "args": [ "build", "tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj", "-f", "netcoreapp1.1", "-c", "Release" ],
+ "args": [ "build", "tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj", "-f", "netcoreapp2.0", "-c", "Release" ],
"showOutput": "always",
"problemMatcher": "$msCompile"
},
{
"taskName": "test",
- "args": ["tests/ImageSharp.Tests/ImageSharp.Tests.csproj", "-c", "release", "-f", "netcoreapp1.1"],
+ "args": ["tests/ImageSharp.Tests/ImageSharp.Tests.csproj", "-c", "release", "-f", "netcoreapp2.0"],
"isTestCommand": true,
"showOutput": "always",
"problemMatcher": "$msCompile"
diff --git a/ImageSharp.sln b/ImageSharp.sln
index f2155f4245..51b63325b7 100644
--- a/ImageSharp.sln
+++ b/ImageSharp.sln
@@ -42,12 +42,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Tests", "tests\I
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Benchmarks", "tests\ImageSharp.Benchmarks\ImageSharp.Benchmarks.csproj", "{2BF743D8-2A06-412D-96D7-F448F00C5EA5}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{7CC6D57E-B916-43B8-B315-A0BB92F260A2}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvatarWithRoundedCorner", "samples\AvatarWithRoundedCorner\AvatarWithRoundedCorner.csproj", "{844FC582-4E78-4371-847D-EFD4D1103578}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ChangeDefaultEncoderOptions", "samples\ChangeDefaultEncoderOptions\ChangeDefaultEncoderOptions.csproj", "{07EE511D-4BAB-4323-BAFC-3AF2BF9366F0}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Sandbox46", "tests\ImageSharp.Sandbox46\ImageSharp.Sandbox46.csproj", "{561B880A-D9EE-44EF-90F5-817C54A9D9AB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp.Formats.Tiff.Tests", "tests\ImageSharp.Formats.Tiff.Tests\ImageSharp.Formats.Tiff.Tests.csproj", "{F74D25AB-1E5C-4272-9FD3-6DBBD3E207AC}"
diff --git a/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj b/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj
deleted file mode 100644
index e000aacf10..0000000000
--- a/samples/AvatarWithRoundedCorner/AvatarWithRoundedCorner.csproj
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
- Exe
- netcoreapp1.1
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/samples/AvatarWithRoundedCorner/Program.cs b/samples/AvatarWithRoundedCorner/Program.cs
deleted file mode 100644
index 087bbc29d5..0000000000
--- a/samples/AvatarWithRoundedCorner/Program.cs
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-using SixLabors.ImageSharp;
-using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing;
-using SixLabors.Primitives;
-using SixLabors.Shapes;
-
-namespace AvatarWithRoundedCorner
-{
- static class Program
- {
- static void Main(string[] args)
- {
- System.IO.Directory.CreateDirectory("output");
- using (var img = Image.Load("fb.jpg"))
- {
- // as generate returns a new IImage make sure we dispose of it
- using (Image destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 20)))
- {
- destRound.Save("output/fb.png");
- }
-
- using (Image destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 100)))
- {
- destRound.Save("output/fb-round.png");
- }
-
- using (Image destRound = img.Clone(x => x.ConvertToAvatar(new Size(200, 200), 150)))
- {
- destRound.Save("output/fb-rounder.png");
- }
-
- using (Image destRound = img.CloneAndConvertToAvatarWithoutApply(new Size(200, 200), 150))
- {
- destRound.Save("output/fb-rounder-without-apply.png");
- }
-
- // the original `img` object has not been altered at all.
- }
- }
-
- // 1. The short way:
- // Implements a full image mutating pipeline operating on IImageProcessingContext
- // We need the dimensions of the resized image to deduce 'IPathCollection' needed to build the corners,
- // so we implement an "inline" image processor by utilizing 'ImageExtensions.Apply()'
- private static IImageProcessingContext ConvertToAvatar(this IImageProcessingContext processingContext, Size size, float cornerRadius)
- {
- return processingContext.Resize(new ResizeOptions
- {
- Size = size,
- Mode = ResizeMode.Crop
- }).Apply(i => ApplyRoundedCorners(i, cornerRadius));
- }
-
- // 2. A more verbose way, avoiding 'Apply()':
- // First we create a resized clone of the image, then we draw the corners on that instance with Mutate().
- private static Image CloneAndConvertToAvatarWithoutApply(this Image image, Size size, float cornerRadius)
- {
- Image result = image.Clone(
- ctx => ctx.Resize(
- new ResizeOptions
- {
- Size = size,
- Mode = ResizeMode.Crop
- }));
-
- ApplyRoundedCorners(result, cornerRadius);
- return result;
- }
-
- // This method can be seen as an inline implementation of an `IImageProcessor`:
- // (The combination of `IImageOperations.Apply()` + this could be replaced with an `IImageProcessor`)
- public static void ApplyRoundedCorners(Image img, float cornerRadius)
- {
- IPathCollection corners = BuildCorners(img.Width, img.Height, cornerRadius);
-
- // mutating in here as we already have a cloned original
- img.Mutate(x => x.Fill(Rgba32.Transparent, corners, new GraphicsOptions(true)
- {
- BlenderMode = PixelBlenderMode.Src // enforces that any part of this shape that has color is punched out of the background
- }));
- }
-
- public static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
- {
- // first create a square
- var rect = new RectangularePolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);
-
- // then cut out of the square a circle so we are left with a corner
- IPath cornerToptLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));
-
- // corner is now a corner shape positions top left
- //lets make 3 more positioned correctly, we can do that by translating the orgional artound the center of the image
- var center = new Vector2(imageWidth / 2F, imageHeight / 2F);
-
- float rightPos = imageWidth - cornerToptLeft.Bounds.Width + 1;
- float bottomPos = imageHeight - cornerToptLeft.Bounds.Height + 1;
-
- // move it across the widthof the image - the width of the shape
- IPath cornerTopRight = cornerToptLeft.RotateDegree(90).Translate(rightPos, 0);
- IPath cornerBottomLeft = cornerToptLeft.RotateDegree(-90).Translate(0, bottomPos);
- IPath cornerBottomRight = cornerToptLeft.RotateDegree(180).Translate(rightPos, bottomPos);
-
- return new PathCollection(cornerToptLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
- }
- }
-}
\ No newline at end of file
diff --git a/samples/AvatarWithRoundedCorner/fb.jpg b/samples/AvatarWithRoundedCorner/fb.jpg
deleted file mode 100644
index 7241890e2e..0000000000
--- a/samples/AvatarWithRoundedCorner/fb.jpg
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:93bb4d6281dc1e845db57e836e0dca30b7a4062e81044efb27ad4d8b1a33130c
-size 15787
diff --git a/samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj b/samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj
deleted file mode 100644
index 5797be0f56..0000000000
--- a/samples/ChangeDefaultEncoderOptions/ChangeDefaultEncoderOptions.csproj
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
- Exe
- netcoreapp1.1
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/samples/ChangeDefaultEncoderOptions/Program.cs b/samples/ChangeDefaultEncoderOptions/Program.cs
deleted file mode 100644
index a8fbd75993..0000000000
--- a/samples/ChangeDefaultEncoderOptions/Program.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using SixLabors.ImageSharp;
-using SixLabors.ImageSharp.Formats.Jpeg;
-
-namespace ChangeDefaultEncoderOptions
-{
- class Program
- {
- static void Main(string[] args)
- {
- // lets switch out the default encoder for jpeg to one
- // that saves at 90 quality and ignores the matadata
- Configuration.Default.SetEncoder(ImageFormats.Jpeg, new JpegEncoder()
- {
- Quality = 90,
- IgnoreMetadata = true
- });
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs b/src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs
index 2d29e23fe5..320c94c96b 100644
--- a/src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs
@@ -122,24 +122,27 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
internal override void Apply(Span scanline, int x, int y)
{
// Create a span for colors
- using (var amountBuffer = new Buffer(scanline.Length))
- using (var overlay = new Buffer(scanline.Length))
+ using (IBuffer amountBuffer = this.Target.MemoryManager.Allocate(scanline.Length))
+ using (IBuffer overlay = this.Target.MemoryManager.Allocate(scanline.Length))
{
+ Span amountSpan = amountBuffer.Span;
+ Span overlaySpan = overlay.Span;
+
int sourceY = (y - this.offsetY) % this.yLength;
int offsetX = x - this.offsetX;
Span sourceRow = this.source.GetPixelRowSpan(sourceY);
for (int i = 0; i < scanline.Length; i++)
{
- amountBuffer[i] = scanline[i] * this.Options.BlendPercentage;
+ amountSpan[i] = scanline[i] * this.Options.BlendPercentage;
int sourceX = (i + offsetX) % this.xLength;
TPixel pixel = sourceRow[sourceX];
- overlay[i] = pixel;
+ overlaySpan[i] = pixel;
}
Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
- this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer);
+ this.Blender.Blend(this.source.MemoryManager, destinationRow, destinationRow, overlaySpan, amountSpan);
}
}
}
diff --git a/src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs
index 844df0e0e9..cc22b26391 100644
--- a/src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs
@@ -152,19 +152,24 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
internal override void Apply(Span scanline, int x, int y)
{
int patternY = y % this.pattern.Height;
- using (var amountBuffer = new Buffer(scanline.Length))
- using (var overlay = new Buffer(scanline.Length))
+ MemoryManager memoryManager = this.Target.MemoryManager;
+
+ using (IBuffer amountBuffer = memoryManager.Allocate(scanline.Length))
+ using (IBuffer overlay = memoryManager.Allocate(scanline.Length))
{
+ Span amountSpan = amountBuffer.Span;
+ Span overlaySpan = overlay.Span;
+
for (int i = 0; i < scanline.Length; i++)
{
- amountBuffer[i] = (scanline[i] * this.Options.BlendPercentage).Clamp(0, 1);
+ amountSpan[i] = (scanline[i] * this.Options.BlendPercentage).Clamp(0, 1);
int patternX = (x + i) % this.pattern.Width;
- overlay[i] = this.pattern[patternY, patternX];
+ overlaySpan[i] = this.pattern[patternY, patternX];
}
Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
- this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer);
+ this.Blender.Blend(memoryManager, destinationRow, destinationRow, overlaySpan, amountSpan);
}
}
}
diff --git a/src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs b/src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
index ca6f7630d9..d8ea435586 100644
--- a/src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
+++ b/src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
@@ -65,21 +65,26 @@ namespace SixLabors.ImageSharp.Drawing.Brushes.Processors
/// scanlineBuffer will be > scanlineWidth but provide and offset in case we want to share a larger buffer across runs.
internal virtual void Apply(Span scanline, int x, int y)
{
- using (var amountBuffer = new Buffer(scanline.Length))
- using (var overlay = new Buffer(scanline.Length))
+ MemoryManager memoryManager = this.Target.MemoryManager;
+
+ using (IBuffer amountBuffer = memoryManager.Allocate(scanline.Length))
+ using (IBuffer overlay = memoryManager.Allocate(scanline.Length))
{
+ Span amountSpan = amountBuffer.Span;
+ Span overlaySpan = overlay.Span;
+
for (int i = 0; i < scanline.Length; i++)
{
if (this.Options.BlendPercentage < 1)
{
- amountBuffer[i] = scanline[i] * this.Options.BlendPercentage;
+ amountSpan[i] = scanline[i] * this.Options.BlendPercentage;
}
- overlay[i] = this[x + i, y];
+ overlaySpan[i] = this[x + i, y];
}
Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
- this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer);
+ this.Blender.Blend(memoryManager, destinationRow, destinationRow, overlaySpan, amountSpan);
}
}
}
diff --git a/src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs b/src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs
index ba2fca4e4b..39afd965c8 100644
--- a/src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs
@@ -144,22 +144,27 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
///
internal override void Apply(Span scanline, int x, int y)
{
- using (var amountBuffer = new Buffer(scanline.Length))
- using (var overlay = new Buffer(scanline.Length))
+ MemoryManager memoryManager = this.Target.MemoryManager;
+
+ using (IBuffer amountBuffer = memoryManager.Allocate(scanline.Length))
+ using (IBuffer overlay = memoryManager.Allocate(scanline.Length))
{
+ Span amountSpan = amountBuffer.Span;
+ Span overlaySpan = overlay.Span;
+
for (int i = 0; i < scanline.Length; i++)
{
- amountBuffer[i] = scanline[i] * this.Options.BlendPercentage;
+ amountSpan[i] = scanline[i] * this.Options.BlendPercentage;
int offsetX = x + i;
// no doubt this one can be optermised further but I can't imagine its
// actually being used and can probably be removed/interalised for now
- overlay[i] = this[offsetX, y];
+ overlaySpan[i] = this[offsetX, y];
}
Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
- this.Blender.Blend(destinationRow, destinationRow, overlay, amountBuffer);
+ this.Blender.Blend(memoryManager, destinationRow, destinationRow, overlaySpan, amountSpan);
}
}
}
diff --git a/src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs b/src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs
index 658164339d..9630c707ef 100644
--- a/src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs
@@ -61,17 +61,14 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
public SolidBrushApplicator(ImageFrame source, TPixel color, GraphicsOptions options)
: base(source, options)
{
- this.Colors = new Buffer(source.Width);
- for (int i = 0; i < this.Colors.Length; i++)
- {
- this.Colors[i] = color;
- }
+ this.Colors = source.MemoryManager.Allocate(source.Width);
+ this.Colors.Span.Fill(color);
}
///
/// Gets the colors.
///
- protected Buffer Colors { get; }
+ protected IBuffer Colors { get; }
///
/// Gets the color for a single pixel.
@@ -81,7 +78,7 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
///
/// The color
///
- internal override TPixel this[int x, int y] => this.Colors[x];
+ internal override TPixel this[int x, int y] => this.Colors.Span[x];
///
public override void Dispose()
@@ -92,23 +89,20 @@ namespace SixLabors.ImageSharp.Drawing.Brushes
///
internal override void Apply(Span scanline, int x, int y)
{
- try
+ Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
+
+ MemoryManager memoryManager = this.Target.MemoryManager;
+
+ using (IBuffer amountBuffer = memoryManager.Allocate(scanline.Length))
{
- Span destinationRow = this.Target.GetPixelRowSpan(y).Slice(x, scanline.Length);
+ Span amountSpan = amountBuffer.Span;
- using (var amountBuffer = new Buffer(scanline.Length))
+ for (int i = 0; i < scanline.Length; i++)
{
- for (int i = 0; i < scanline.Length; i++)
- {
- amountBuffer[i] = scanline[i] * this.Options.BlendPercentage;
- }
-
- this.Blender.Blend(destinationRow, destinationRow, this.Colors, amountBuffer);
+ amountSpan[i] = scanline[i] * this.Options.BlendPercentage;
}
- }
- catch (Exception)
- {
- throw;
+
+ this.Blender.Blend(memoryManager, destinationRow, destinationRow, this.Colors.Span, amountSpan);
}
}
}
diff --git a/src/ImageSharp.Drawing/DrawImage.cs b/src/ImageSharp.Drawing/DrawImage.cs
index d55e224162..f1db72db60 100644
--- a/src/ImageSharp.Drawing/DrawImage.cs
+++ b/src/ImageSharp.Drawing/DrawImage.cs
@@ -18,24 +18,13 @@ namespace SixLabors.ImageSharp
/// The image this method extends.
/// The image to blend with the currently processing image.
/// The pixel format.
- /// The size to draw the blended image.
/// The location to draw the blended image.
/// The options.
/// The .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Size size, Point location, GraphicsOptions options)
+ public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, Point location, GraphicsOptions options)
where TPixel : struct, IPixel
{
- if (size == default(Size))
- {
- size = new Size(image.Width, image.Height);
- }
-
- if (location == default(Point))
- {
- location = Point.Empty;
- }
-
- source.ApplyProcessor(new DrawImageProcessor(image, size, location, options));
+ source.ApplyProcessor(new DrawImageProcessor(image, location, options));
return source;
}
@@ -45,14 +34,14 @@ namespace SixLabors.ImageSharp
/// The pixel format.
/// The image this method extends.
/// The image to blend with the currently processing image.
- /// The opacity of the image image to blend. Must be between 0 and 1.
+ /// The opacity of the image to blend. Must be between 0 and 1.
/// The .
- public static IImageProcessingContext Blend(this IImageProcessingContext source, Image image, float percent)
+ public static IImageProcessingContext Blend(this IImageProcessingContext source, Image image, float opacity)
where TPixel : struct, IPixel
{
GraphicsOptions options = GraphicsOptions.Default;
- options.BlendPercentage = percent;
- return DrawImage(source, image, default(Size), default(Point), options);
+ options.BlendPercentage = opacity;
+ return DrawImage(source, image, Point.Empty, options);
}
///
@@ -62,15 +51,15 @@ namespace SixLabors.ImageSharp
/// The image this method extends.
/// The image to blend with the currently processing image.
/// The blending mode.
- /// The opacity of the image image to blend. Must be between 0 and 1.
+ /// The opacity of the image to blend. Must be between 0 and 1.
/// The .
- public static IImageProcessingContext Blend(this IImageProcessingContext source, Image image, PixelBlenderMode blender, float percent)
+ public static IImageProcessingContext Blend(this IImageProcessingContext source, Image image, PixelBlenderMode blender, float opacity)
where TPixel : struct, IPixel
{
GraphicsOptions options = GraphicsOptions.Default;
- options.BlendPercentage = percent;
+ options.BlendPercentage = opacity;
options.BlenderMode = blender;
- return DrawImage(source, image, default(Size), default(Point), options);
+ return DrawImage(source, image, Point.Empty, options);
}
///
@@ -79,12 +68,12 @@ namespace SixLabors.ImageSharp
/// The pixel format.
/// The image this method extends.
/// The image to blend with the currently processing image.
- /// The options, including the blending type and belnding amount.
+ /// The options, including the blending type and blending amount.
/// The .
public static IImageProcessingContext Blend(this IImageProcessingContext source, Image image, GraphicsOptions options)
where TPixel : struct, IPixel
{
- return DrawImage(source, image, default(Size), default(Point), options);
+ return DrawImage(source, image, Point.Empty, options);
}
///
@@ -93,16 +82,15 @@ namespace SixLabors.ImageSharp
/// The image this method extends.
/// The image to blend with the currently processing image.
/// The pixel format.
- /// The opacity of the image image to blend. Must be between 0 and 1.
- /// The size to draw the blended image.
+ /// The opacity of the image to blend. Must be between 0 and 1.
/// The location to draw the blended image.
/// The .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float percent, Size size, Point location)
+ public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, float opacity, Point location)
where TPixel : struct, IPixel
{
GraphicsOptions options = GraphicsOptions.Default;
- options.BlendPercentage = percent;
- return source.DrawImage(image, size, location, options);
+ options.BlendPercentage = opacity;
+ return source.DrawImage(image, location, options);
}
///
@@ -112,17 +100,16 @@ namespace SixLabors.ImageSharp
/// The image to blend with the currently processing image.
/// The pixel format.
/// The type of bending to apply.
- /// The opacity of the image image to blend. Must be between 0 and 1.
- /// The size to draw the blended image.
+ /// The opacity of the image to blend. Must be between 0 and 1.
/// The location to draw the blended image.
/// The .
- public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelBlenderMode blender, float percent, Size size, Point location)
+ public static IImageProcessingContext DrawImage(this IImageProcessingContext source, Image image, PixelBlenderMode blender, float opacity, Point location)
where TPixel : struct, IPixel
{
GraphicsOptions options = GraphicsOptions.Default;
options.BlenderMode = blender;
- options.BlendPercentage = percent;
- return source.DrawImage(image, size, location, options);
+ options.BlendPercentage = opacity;
+ return source.DrawImage(image, location, options);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp.Drawing/Paths/ShapePath.cs b/src/ImageSharp.Drawing/Paths/ShapePath.cs
index 61f1291c45..4c22787195 100644
--- a/src/ImageSharp.Drawing/Paths/ShapePath.cs
+++ b/src/ImageSharp.Drawing/Paths/ShapePath.cs
@@ -4,6 +4,8 @@
using System;
using System.Buffers;
using System.Numerics;
+
+using SixLabors.ImageSharp.Memory;
using SixLabors.Shapes;
namespace SixLabors.ImageSharp.Drawing
diff --git a/src/ImageSharp.Drawing/Paths/ShapeRegion.cs b/src/ImageSharp.Drawing/Paths/ShapeRegion.cs
index a96b03dd04..cc27f7fbb8 100644
--- a/src/ImageSharp.Drawing/Paths/ShapeRegion.cs
+++ b/src/ImageSharp.Drawing/Paths/ShapeRegion.cs
@@ -46,18 +46,17 @@ namespace SixLabors.ImageSharp.Drawing
{
var start = new PointF(this.Bounds.Left - 1, y);
var end = new PointF(this.Bounds.Right + 1, y);
- using (var innerBuffer = new Buffer(buffer.Length))
- {
- PointF[] array = innerBuffer.Array;
- int count = this.Shape.FindIntersections(start, end, array, 0);
- for (int i = 0; i < count; i++)
- {
- buffer[i + offset] = array[i].X;
- }
+ // TODO: This is a temporary workaround because of the lack of Span API-s on IPath. We should use MemoryManager.Allocate() here!
+ PointF[] innerBuffer = new PointF[buffer.Length];
+ int count = this.Shape.FindIntersections(start, end, innerBuffer, 0);
- return count;
+ for (int i = 0; i < count; i++)
+ {
+ buffer[i + offset] = innerBuffer[i].X;
}
+
+ return count;
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs
index 47763c0aaf..632b4d449d 100644
--- a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs
+++ b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs
@@ -19,93 +19,77 @@ namespace SixLabors.ImageSharp.Drawing.Processors
internal class DrawImageProcessor : ImageProcessor
where TPixel : struct, IPixel
{
- private readonly PixelBlender blender;
-
///
/// Initializes a new instance of the class.
///
/// The image to blend with the currently processing image.
- /// The size to draw the blended image.
/// The location to draw the blended image.
- /// The opacity of the image to blend. Between 0 and 100.
- public DrawImageProcessor(Image image, Size size, Point location, GraphicsOptions options)
+ /// The opacity of the image to blend. Between 0 and 1.
+ public DrawImageProcessor(Image image, Point location, GraphicsOptions options)
{
Guard.MustBeBetweenOrEqualTo(options.BlendPercentage, 0, 1, nameof(options.BlendPercentage));
+
this.Image = image;
- this.Size = size;
- this.Alpha = options.BlendPercentage;
- this.blender = PixelOperations.Instance.GetPixelBlender(options.BlenderMode);
+ this.Opacity = options.BlendPercentage;
+ this.Blender = PixelOperations.Instance.GetPixelBlender(options.BlenderMode);
this.Location = location;
}
///
- /// Gets the image to blend.
+ /// Gets the image to blend
///
public Image Image { get; }
///
- /// Gets the alpha percentage value.
+ /// Gets the opacity of the image to blend
///
- public float Alpha { get; }
+ public float Opacity { get; }
///
- /// Gets the size to draw the blended image.
+ /// Gets the pixel blender
///
- public Size Size { get; }
+ public PixelBlender Blender { get; }
///
- /// Gets the location to draw the blended image.
+ /// Gets the location to draw the blended image
///
public Point Location { get; }
///
protected override void OnApply(ImageFrame source, Rectangle sourceRectangle, Configuration configuration)
{
- Image disposableImage = null;
Image targetImage = this.Image;
+ PixelBlender blender = this.Blender;
+ int locationY = this.Location.Y;
- try
- {
- if (targetImage.Size() != this.Size)
- {
- targetImage = disposableImage = this.Image.Clone(x => x.Resize(this.Size.Width, this.Size.Height));
- }
+ // Align start/end positions.
+ Rectangle bounds = targetImage.Bounds();
- // Align start/end positions.
- Rectangle bounds = targetImage.Bounds();
- int minX = Math.Max(this.Location.X, sourceRectangle.X);
- int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width);
- maxX = Math.Min(this.Location.X + this.Size.Width, maxX);
- int targetX = minX - this.Location.X;
+ int minX = Math.Max(this.Location.X, sourceRectangle.X);
+ int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width);
+ int targetX = minX - this.Location.X;
- int minY = Math.Max(this.Location.Y, sourceRectangle.Y);
- int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom);
+ int minY = Math.Max(this.Location.Y, sourceRectangle.Y);
+ int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom);
- maxY = Math.Min(this.Location.Y + this.Size.Height, maxY);
+ int width = maxX - minX;
- int width = maxX - minX;
- using (var amount = new Buffer(width))
- {
- for (int i = 0; i < width; i++)
- {
- amount[i] = this.Alpha;
- }
+ MemoryManager memoryManager = this.Image.GetConfiguration().MemoryManager;
- Parallel.For(
- minY,
- maxY,
- configuration.ParallelOptions,
- y =>
- {
- Span background = source.GetPixelRowSpan(y).Slice(minX, width);
- Span foreground = targetImage.GetPixelRowSpan(y - this.Location.Y).Slice(targetX, width);
- this.blender.Blend(background, background, foreground, amount);
- });
- }
- }
- finally
+ using (IBuffer amount = memoryManager.Allocate(width))
{
- disposableImage?.Dispose();
+ amount.Span.Fill(this.Opacity);
+
+ Parallel.For(
+ minY,
+ maxY,
+ configuration.ParallelOptions,
+ y =>
+ {
+ Span background = source.GetPixelRowSpan(y).Slice(minX, width);
+ Span foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width);
+ blender.Blend(memoryManager, background, background, foreground, amount.Span);
+ });
}
}
}
diff --git a/src/ImageSharp.Drawing/Processors/FillProcessor.cs b/src/ImageSharp.Drawing/Processors/FillProcessor.cs
index 679ca6a228..3bf18a37ba 100644
--- a/src/ImageSharp.Drawing/Processors/FillProcessor.cs
+++ b/src/ImageSharp.Drawing/Processors/FillProcessor.cs
@@ -66,25 +66,25 @@ namespace SixLabors.ImageSharp.Drawing.Processors
int width = maxX - minX;
- using (var amount = new Buffer(width))
- using (BrushApplicator applicator = this.brush.CreateApplicator(source, sourceRectangle, this.options))
+ using (IBuffer amount = source.MemoryManager.Allocate(width))
+ using (BrushApplicator applicator = this.brush.CreateApplicator(
+ source,
+ sourceRectangle,
+ this.options))
{
- for (int i = 0; i < width; i++)
- {
- amount[i] = this.options.BlendPercentage;
- }
+ amount.Span.Fill(this.options.BlendPercentage);
- Parallel.For(
+ Parallel.For(
minY,
maxY,
configuration.ParallelOptions,
y =>
- {
- int offsetY = y - startY;
- int offsetX = minX - startX;
+ {
+ int offsetY = y - startY;
+ int offsetX = minX - startX;
- applicator.Apply(amount, offsetX, offsetY);
- });
+ applicator.Apply(amount.Span, offsetX, offsetY);
+ });
}
}
}
diff --git a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
index b6ef4be218..076785526c 100644
--- a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
+++ b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
@@ -78,8 +78,6 @@ namespace SixLabors.ImageSharp.Drawing.Processors
return; // no effect inside image;
}
- ArrayPool arrayPool = ArrayPool.Shared;
-
int maxIntersections = region.MaxIntersections;
float subpixelCount = 4;
@@ -100,101 +98,94 @@ namespace SixLabors.ImageSharp.Drawing.Processors
using (BrushApplicator applicator = this.Brush.CreateApplicator(source, rect, this.Options))
{
- float[] buffer = arrayPool.Rent(maxIntersections);
int scanlineWidth = maxX - minX;
- using (var scanline = new Buffer(scanlineWidth))
+ using (BasicArrayBuffer buffer = source.MemoryManager.AllocateFake(maxIntersections))
+ using (BasicArrayBuffer scanline = source.MemoryManager.AllocateFake(scanlineWidth))
{
- try
+ bool scanlineDirty = true;
+ for (int y = minY; y < maxY; y++)
{
- bool scanlineDirty = true;
- for (int y = minY; y < maxY; y++)
+ if (scanlineDirty)
{
- if (scanlineDirty)
+ // clear the buffer
+ for (int x = 0; x < scanlineWidth; x++)
{
- // clear the buffer
- for (int x = 0; x < scanlineWidth; x++)
- {
- scanline[x] = 0;
- }
-
- scanlineDirty = false;
+ scanline[x] = 0;
}
- float subpixelFraction = 1f / subpixelCount;
- float subpixelFractionPoint = subpixelFraction / subpixelCount;
- for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction)
- {
- int pointsFound = region.Scan(subPixel + offset, buffer, 0);
- if (pointsFound == 0)
- {
- // nothing on this line skip
- continue;
- }
+ scanlineDirty = false;
+ }
- QuickSort(new Span(buffer, 0, pointsFound));
+ float subpixelFraction = 1f / subpixelCount;
+ float subpixelFractionPoint = subpixelFraction / subpixelCount;
+ for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction)
+ {
+ int pointsFound = region.Scan(subPixel + offset, buffer.Array, 0);
+ if (pointsFound == 0)
+ {
+ // nothing on this line skip
+ continue;
+ }
- for (int point = 0; point < pointsFound; point += 2)
- {
- // points will be paired up
- float scanStart = buffer[point] - minX;
- float scanEnd = buffer[point + 1] - minX;
- int startX = (int)MathF.Floor(scanStart + offset);
- int endX = (int)MathF.Floor(scanEnd + offset);
+ QuickSort(new Span(buffer.Array, 0, pointsFound));
- if (startX >= 0 && startX < scanline.Length)
- {
- for (float x = scanStart; x < startX + 1; x += subpixelFraction)
- {
- scanline[startX] += subpixelFractionPoint;
- scanlineDirty = true;
- }
- }
+ for (int point = 0; point < pointsFound; point += 2)
+ {
+ // points will be paired up
+ float scanStart = buffer[point] - minX;
+ float scanEnd = buffer[point + 1] - minX;
+ int startX = (int)MathF.Floor(scanStart + offset);
+ int endX = (int)MathF.Floor(scanEnd + offset);
- if (endX >= 0 && endX < scanline.Length)
+ if (startX >= 0 && startX < scanline.Length)
+ {
+ for (float x = scanStart; x < startX + 1; x += subpixelFraction)
{
- for (float x = endX; x < scanEnd; x += subpixelFraction)
- {
- scanline[endX] += subpixelFractionPoint;
- scanlineDirty = true;
- }
+ scanline[startX] += subpixelFractionPoint;
+ scanlineDirty = true;
}
+ }
- int nextX = startX + 1;
- endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge
- nextX = Math.Max(nextX, 0);
- for (int x = nextX; x < endX; x++)
+ if (endX >= 0 && endX < scanline.Length)
+ {
+ for (float x = endX; x < scanEnd; x += subpixelFraction)
{
- scanline[x] += subpixelFraction;
+ scanline[endX] += subpixelFractionPoint;
scanlineDirty = true;
}
}
+
+ int nextX = startX + 1;
+ endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge
+ nextX = Math.Max(nextX, 0);
+ for (int x = nextX; x < endX; x++)
+ {
+ scanline[x] += subpixelFraction;
+ scanlineDirty = true;
+ }
}
+ }
- if (scanlineDirty)
+ if (scanlineDirty)
+ {
+ if (!this.Options.Antialias)
{
- if (!this.Options.Antialias)
+ for (int x = 0; x < scanlineWidth; x++)
{
- for (int x = 0; x < scanlineWidth; x++)
+ if (scanline[x] >= 0.5)
+ {
+ scanline[x] = 1;
+ }
+ else
{
- if (scanline[x] >= 0.5)
- {
- scanline[x] = 1;
- }
- else
- {
- scanline[x] = 0;
- }
+ scanline[x] = 0;
}
}
-
- applicator.Apply(scanline, minX, y);
}
+
+ applicator.Apply(scanline.Span, minX, y);
}
}
- finally
- {
- arrayPool.Return(buffer);
- }
}
}
}
diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
index 0acb846c50..24d2dd4cc4 100644
--- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
+++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@@ -88,6 +89,14 @@ namespace SixLabors.ImageSharp.Advanced
where TPixel : struct, IPixel
=> source.Frames.RootFrame.GetPixelRowSpan(row);
+ ///
+ /// Gets the assigned to 'source'.
+ ///
+ /// The source image
+ /// Returns the configuration.
+ internal static MemoryManager GetMemoryManager(this IConfigurable source)
+ => GetConfiguration(source).MemoryManager;
+
///
/// Gets the span to the backing buffer.
///
@@ -140,6 +149,6 @@ namespace SixLabors.ImageSharp.Advanced
/// A reference to the element.
private static ref TPixel DangerousGetPinnableReferenceToPixelBuffer(IPixelSource source)
where TPixel : struct, IPixel
- => ref source.PixelBuffer.Span.DangerousGetPinnableReference();
+ => ref MemoryMarshal.GetReference(source.PixelBuffer.Span);
}
}
diff --git a/src/ImageSharp/ApplyProcessors.cs b/src/ImageSharp/ApplyProcessors.cs
index 58a952c406..c4954ef0d1 100644
--- a/src/ImageSharp/ApplyProcessors.cs
+++ b/src/ImageSharp/ApplyProcessors.cs
@@ -4,7 +4,6 @@
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing;
namespace SixLabors.ImageSharp
{
diff --git a/src/ImageSharp/ColorSpaces/CieLab.cs b/src/ImageSharp/ColorSpaces/CieLab.cs
index 107be4cb2b..cb08d08bf9 100644
--- a/src/ImageSharp/ColorSpaces/CieLab.cs
+++ b/src/ImageSharp/ColorSpaces/CieLab.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents a CIE L*a*b* 1976 color.
///
///
- internal struct CieLab : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct CieLab : IColorVector, IEquatable, IAlmostEquatable
{
///
/// D50 standard illuminant.
diff --git a/src/ImageSharp/ColorSpaces/CieLch.cs b/src/ImageSharp/ColorSpaces/CieLch.cs
index 834ef56a89..94443fd863 100644
--- a/src/ImageSharp/ColorSpaces/CieLch.cs
+++ b/src/ImageSharp/ColorSpaces/CieLch.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents the CIE L*C*h°, cylindrical form of the CIE L*a*b* 1976 color.
///
///
- internal struct CieLch : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct CieLch : IColorVector, IEquatable, IAlmostEquatable
{
///
/// D50 standard illuminant.
diff --git a/src/ImageSharp/ColorSpaces/CieLchuv.cs b/src/ImageSharp/ColorSpaces/CieLchuv.cs
index f35914d641..705b770d35 100644
--- a/src/ImageSharp/ColorSpaces/CieLchuv.cs
+++ b/src/ImageSharp/ColorSpaces/CieLchuv.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents the CIE L*C*h°, cylindrical form of the CIE L*u*v* 1976 color.
///
///
- internal struct CieLchuv : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct CieLchuv : IColorVector, IEquatable, IAlmostEquatable
{
///
/// D50 standard illuminant.
diff --git a/src/ImageSharp/ColorSpaces/CieLuv.cs b/src/ImageSharp/ColorSpaces/CieLuv.cs
index 9b52517083..b0ae048ab7 100644
--- a/src/ImageSharp/ColorSpaces/CieLuv.cs
+++ b/src/ImageSharp/ColorSpaces/CieLuv.cs
@@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// attempted perceptual uniformity
///
///
- internal struct CieLuv : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct CieLuv : IColorVector, IEquatable, IAlmostEquatable
{
///
/// D65 standard illuminant.
diff --git a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
index d9767d45ea..d0a70dd191 100644
--- a/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyChromaticityCoordinates.cs
@@ -6,12 +6,13 @@ using System.ComponentModel;
using System.Numerics;
using System.Runtime.CompilerServices;
+// ReSharper disable CompareOfFloatsByEqualityOperator
namespace SixLabors.ImageSharp.ColorSpaces
{
///
/// Represents the coordinates of CIEXY chromaticity space
///
- internal struct CieXyChromaticityCoordinates : IEquatable, IAlmostEquatable
+ internal readonly struct CieXyChromaticityCoordinates : IEquatable, IAlmostEquatable
{
///
/// Represents a that has X, Y values set to zero.
@@ -143,7 +144,8 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(CieXyChromaticityCoordinates other)
{
- return this.backingVector.Equals(other.backingVector);
+ // The memberwise comparison here is a workaround for https://github.com/dotnet/coreclr/issues/16443
+ return this.X == other.X && this.Y == other.Y;
}
///
diff --git a/src/ImageSharp/ColorSpaces/CieXyy.cs b/src/ImageSharp/ColorSpaces/CieXyy.cs
index d5ef4b15d3..751830a0ba 100644
--- a/src/ImageSharp/ColorSpaces/CieXyy.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyy.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents an CIE xyY 1931 color
///
///
- internal struct CieXyy : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct CieXyy : IColorVector, IEquatable, IAlmostEquatable
{
///
/// Represents a that has X, Y, and Y values set to zero.
diff --git a/src/ImageSharp/ColorSpaces/CieXyz.cs b/src/ImageSharp/ColorSpaces/CieXyz.cs
index 908408000a..0f1866009b 100644
--- a/src/ImageSharp/ColorSpaces/CieXyz.cs
+++ b/src/ImageSharp/ColorSpaces/CieXyz.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents an CIE XYZ 1931 color
///
///
- internal struct CieXyz : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct CieXyz : IColorVector, IEquatable, IAlmostEquatable
{
///
/// Represents a that has X, Y, and Z values set to zero.
diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs
index 2a58a5762a..2eb148a8c3 100644
--- a/src/ImageSharp/ColorSpaces/Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Cmyk.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents an CMYK (cyan, magenta, yellow, keyline) color.
///
- internal struct Cmyk : IEquatable, IAlmostEquatable
+ internal readonly struct Cmyk : IEquatable, IAlmostEquatable
{
///
/// Represents a that has C, M, Y, and K values set to zero.
diff --git a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
index de13b97eb8..6844e3a3ca 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/ColorSpaceConverter.Rgb.cs
@@ -184,8 +184,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
Rgb rgb = YCbCrAndRgbConverter.Convert(color);
// Adaptation
- // TODO: Check this!
- return rgb.WorkingSpace.Equals(this.TargetRgbWorkingSpace) ? rgb : this.Adapt(rgb);
+ return this.Adapt(rgb);
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs
index 2ec79b353b..b40a02af76 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbAndCieXyzConverterBase.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
internal abstract class LinearRgbAndCieXyzConverterBase
{
///
- /// Geturns the correct matrix to convert between the Rgb and CieXyz color space.
+ /// Returns the correct matrix to convert between the Rgb and CieXyz color space.
///
/// The Rgb working space.
/// The based on the chromaticity and working space.
@@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
Vector3 vector = Vector3.Transform(workingSpace.WhitePoint.Vector, inverseXyzMatrix);
- // Use transposed Rows/Coloumns
+ // Use transposed Rows/Columns
// TODO: Is there a built in method for this multiplication?
return new Matrix4x4
{
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs
index 19d4130373..bf36e252a2 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/LinearRgbToCieXyzConverter.cs
@@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
public CieXyz Convert(LinearRgb input)
{
DebugGuard.NotNull(input, nameof(input));
- Guard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal.");
+ DebugGuard.IsTrue(input.WorkingSpace.Equals(this.SourceWorkingSpace), nameof(input.WorkingSpace), "Input and source working spaces must be equal.");
Vector3 vector = Vector3.Transform(input.Vector, this.conversionMatrix);
return new CieXyz(vector);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
index 8a2c66a80c..5a5c39647f 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Rgb/RgbWorkingSpace.cs
@@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSap
///
/// Trivial implementation of
///
- internal struct RgbWorkingSpace : IRgbWorkingSpace
+ internal readonly struct RgbWorkingSpace : IRgbWorkingSpace
{
///
/// Initializes a new instance of the struct.
diff --git a/src/ImageSharp/ColorSpaces/Hsl.cs b/src/ImageSharp/ColorSpaces/Hsl.cs
index cf880f1548..1944ac0c6b 100644
--- a/src/ImageSharp/ColorSpaces/Hsl.cs
+++ b/src/ImageSharp/ColorSpaces/Hsl.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a Hsl (hue, saturation, lightness) color.
///
- internal struct Hsl : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct Hsl : IColorVector, IEquatable, IAlmostEquatable
{
///
/// Represents a that has H, S, and L values set to zero.
diff --git a/src/ImageSharp/ColorSpaces/Hsv.cs b/src/ImageSharp/ColorSpaces/Hsv.cs
index 9f47393792..45ffd7f121 100644
--- a/src/ImageSharp/ColorSpaces/Hsv.cs
+++ b/src/ImageSharp/ColorSpaces/Hsv.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents a HSV (hue, saturation, value) color. Also known as HSB (hue, saturation, brightness).
///
- internal struct Hsv : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct Hsv : IColorVector, IEquatable, IAlmostEquatable
{
///
/// Represents a that has H, S, and V values set to zero.
diff --git a/src/ImageSharp/ColorSpaces/HunterLab.cs b/src/ImageSharp/ColorSpaces/HunterLab.cs
index b5ba7c86c7..de42518d76 100644
--- a/src/ImageSharp/ColorSpaces/HunterLab.cs
+++ b/src/ImageSharp/ColorSpaces/HunterLab.cs
@@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// Represents an Hunter LAB color.
///
///
- internal struct HunterLab : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct HunterLab : IColorVector, IEquatable, IAlmostEquatable
{
///
/// D50 standard illuminant.
diff --git a/src/ImageSharp/ColorSpaces/LinearRgb.cs b/src/ImageSharp/ColorSpaces/LinearRgb.cs
index 07889c3529..b8c446285a 100644
--- a/src/ImageSharp/ColorSpaces/LinearRgb.cs
+++ b/src/ImageSharp/ColorSpaces/LinearRgb.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents an linear Rgb color with specified working space
///
- internal struct LinearRgb : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct LinearRgb : IColorVector, IEquatable, IAlmostEquatable
{
///
/// Represents a that has R, G, and B values set to zero.
diff --git a/src/ImageSharp/ColorSpaces/Lms.cs b/src/ImageSharp/ColorSpaces/Lms.cs
index 82c291de3d..72ac16f213 100644
--- a/src/ImageSharp/ColorSpaces/Lms.cs
+++ b/src/ImageSharp/ColorSpaces/Lms.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
/// named after their responsivity (sensitivity) at long, medium and short wavelengths.
///
///
- internal struct Lms : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct Lms : IColorVector, IEquatable, IAlmostEquatable
{
///
/// Represents a that has L, M, and S values set to zero.
diff --git a/src/ImageSharp/ColorSpaces/Rgb.cs b/src/ImageSharp/ColorSpaces/Rgb.cs
index 8ac8411b20..53fa6086df 100644
--- a/src/ImageSharp/ColorSpaces/Rgb.cs
+++ b/src/ImageSharp/ColorSpaces/Rgb.cs
@@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
/// Represents an RGB color with specified working space
///
- internal struct Rgb : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct Rgb : IColorVector, IEquatable, IAlmostEquatable
{
///
/// Represents a that has R, G, and B values set to zero.
diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs
index 708a74308a..44a0b245d5 100644
--- a/src/ImageSharp/ColorSpaces/YCbCr.cs
+++ b/src/ImageSharp/ColorSpaces/YCbCr.cs
@@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
///
///
///
- internal struct YCbCr : IColorVector, IEquatable, IAlmostEquatable
+ internal readonly struct YCbCr : IColorVector, IEquatable, IAlmostEquatable
{
///
/// Represents a that has Y, Cb, and Cr values set to zero.
diff --git a/src/ImageSharp/Common/Extensions/SimdUtils.cs b/src/ImageSharp/Common/Extensions/SimdUtils.cs
index 0188bc03cf..7b77fefcac 100644
--- a/src/ImageSharp/Common/Extensions/SimdUtils.cs
+++ b/src/ImageSharp/Common/Extensions/SimdUtils.cs
@@ -76,14 +76,14 @@ namespace SixLabors.ImageSharp
return;
}
- ref Vector srcBase = ref Unsafe.As>(ref source.DangerousGetPinnableReference());
- ref Octet.OfByte destBase = ref Unsafe.As(ref dest.DangerousGetPinnableReference());
+ ref Vector srcBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Octet.OfByte destBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
int n = source.Length / 8;
Vector magick = new Vector(32768.0f);
Vector scale = new Vector(255f) / new Vector(256f);
- // need to copy to a temporal struct, because
+ // need to copy to a temporary struct, because
// SimdUtils.Octet.OfUInt32 temp = Unsafe.As, SimdUtils.Octet.OfUInt32>(ref x)
// does not work. TODO: This might be a CoreClr bug, need to ask/report
var temp = default(Octet.OfUInt32);
@@ -117,14 +117,14 @@ namespace SixLabors.ImageSharp
return;
}
- ref Vector srcBase = ref Unsafe.As>(ref source.DangerousGetPinnableReference());
- ref Octet.OfByte destBase = ref Unsafe.As(ref dest.DangerousGetPinnableReference());
+ ref Vector srcBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(source));
+ ref Octet.OfByte destBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
int n = source.Length / 8;
Vector magick = new Vector(32768.0f);
Vector scale = new Vector(255f) / new Vector(256f);
- // need to copy to a temporal struct, because
+ // need to copy to a temporary struct, because
// SimdUtils.Octet.OfUInt32 temp = Unsafe.As, SimdUtils.Octet.OfUInt32>(ref x)
// does not work. TODO: This might be a CoreClr bug, need to ask/report
var temp = default(Octet.OfUInt32);
diff --git a/src/ImageSharp/Common/Extensions/StreamExtensions.cs b/src/ImageSharp/Common/Extensions/StreamExtensions.cs
index b717abab1c..7a9a34ac1a 100644
--- a/src/ImageSharp/Common/Extensions/StreamExtensions.cs
+++ b/src/ImageSharp/Common/Extensions/StreamExtensions.cs
@@ -29,23 +29,16 @@ namespace SixLabors.ImageSharp
}
else
{
- byte[] foo = ArrayPool.Shared.Rent(count);
- try
+ byte[] foo = new byte[count];
+ while (count > 0)
{
- while (count > 0)
+ int bytesRead = stream.Read(foo, 0, count);
+ if (bytesRead == 0)
{
- int bytesRead = stream.Read(foo, 0, count);
- if (bytesRead == 0)
- {
- break;
- }
-
- count -= bytesRead;
+ break;
}
- }
- finally
- {
- ArrayPool.Shared.Return(foo);
+
+ count -= bytesRead;
}
}
}
diff --git a/src/ImageSharp/Common/Helpers/ParallelFor.cs b/src/ImageSharp/Common/Helpers/ParallelFor.cs
new file mode 100644
index 0000000000..da91259051
--- /dev/null
+++ b/src/ImageSharp/Common/Helpers/ParallelFor.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Threading.Tasks;
+using SixLabors.ImageSharp.Memory;
+
+namespace SixLabors.ImageSharp
+{
+ ///
+ /// Utility methods for Parallel.For() execution. Use this instead of raw calls!
+ ///
+ internal static class ParallelFor
+ {
+ ///
+ /// Helper method to execute Parallel.For using the settings in
+ ///
+ public static void WithConfiguration(int fromInclusive, int toExclusive, Configuration configuration, Action body)
+ {
+ Parallel.For(fromInclusive, toExclusive, configuration.ParallelOptions, body);
+ }
+
+ ///
+ /// Helper method to execute Parallel.For with temporary worker buffer shared between executing tasks.
+ /// The buffer is not guaranteed to be clean!
+ ///
+ /// The value type of the buffer
+ /// The start index, inclusive.
+ /// The end index, exclusive.
+ /// The used for getting the and
+ /// The length of the requested parallel buffer
+ /// The delegate that is invoked once per iteration.
+ public static void WithTemporaryBuffer(
+ int fromInclusive,
+ int toExclusive,
+ Configuration configuration,
+ int bufferLength,
+ Action> body)
+ where T : struct
+ {
+ MemoryManager memoryManager = configuration.MemoryManager;
+ ParallelOptions parallelOptions = configuration.ParallelOptions;
+
+ IBuffer InitBuffer()
+ {
+ return memoryManager.Allocate(bufferLength);
+ }
+
+ void CleanUpBuffer(IBuffer buffer)
+ {
+ buffer.Dispose();
+ }
+
+ IBuffer BodyFunc(int i, ParallelLoopState state, IBuffer buffer)
+ {
+ body(i, buffer);
+ return buffer;
+ }
+
+ Parallel.For(fromInclusive, toExclusive, parallelOptions, InitBuffer, BodyFunc, CleanUpBuffer);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Configuration.cs b/src/ImageSharp/Configuration.cs
index 7401035331..d41e48678b 100644
--- a/src/ImageSharp/Configuration.cs
+++ b/src/ImageSharp/Configuration.cs
@@ -1,261 +1,145 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using SixLabors.ImageSharp.Formats;
-using SixLabors.ImageSharp.Formats.Bmp;
-using SixLabors.ImageSharp.Formats.Gif;
-using SixLabors.ImageSharp.Formats.Jpeg;
-using SixLabors.ImageSharp.Formats.Png;
-using SixLabors.ImageSharp.IO;
-
-namespace SixLabors.ImageSharp
-{
- ///
- /// Provides initialization code which allows extending the library.
- ///
- public sealed class Configuration
- {
- ///
- /// A lazily initialized configuration default instance.
- ///
- private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance);
-
- ///
- /// The list of supported keyed to mime types.
- ///
- private readonly ConcurrentDictionary mimeTypeEncoders = new ConcurrentDictionary();
-
- ///
- /// The list of supported keyed to mime types.
- ///
- private readonly ConcurrentDictionary mimeTypeDecoders = new ConcurrentDictionary();
-
- ///
- /// The list of supported s.
- ///
- private readonly ConcurrentBag imageFormats = new ConcurrentBag();
-
- ///
- /// The list of supported s.
- ///
- private ConcurrentBag imageFormatDetectors = new ConcurrentBag();
-
- ///
- /// Initializes a new instance of the class.
- ///
- public Configuration()
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// A collection of configuration modules to register
- public Configuration(params IConfigurationModule[] configurationModules)
- {
- if (configurationModules != null)
- {
- foreach (IConfigurationModule p in configurationModules)
- {
- p.Configure(this);
- }
- }
- }
-
- ///
- /// Gets the default instance.
- ///
- public static Configuration Default { get; } = Lazy.Value;
-
- ///
- /// Gets the global parallel options for processing tasks in parallel.
- ///
- public ParallelOptions ParallelOptions { get; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
-
- ///
- /// Gets the currently registered s.
- ///
- public IEnumerable ImageFormats => this.imageFormats;
-
- ///
- /// Gets the maximum header size of all the formats.
- ///
- internal int MaxHeaderSize { get; private set; }
-
- ///
- /// Gets the currently registered s.
- ///
- internal IEnumerable FormatDetectors => this.imageFormatDetectors;
-
- ///
- /// Gets the currently registered s.
- ///
- internal IEnumerable> ImageDecoders => this.mimeTypeDecoders;
-
- ///
- /// Gets the currently registered s.
- ///
- internal IEnumerable> ImageEncoders => this.mimeTypeEncoders;
-
-#if !NETSTANDARD1_1
- ///
- /// Gets or sets the filesystem helper for accessing the local file system.
- ///
- internal IFileSystem FileSystem { get; set; } = new LocalFileSystem();
-#endif
-
- ///
- /// Gets or sets the image operations provider factory.
- ///
- internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory();
-
- ///
- /// Registers a new format provider.
- ///
- /// The configuration provider to call configure on.
- public void Configure(IConfigurationModule configuration)
- {
- Guard.NotNull(configuration, nameof(configuration));
- configuration.Configure(this);
- }
-
- ///
- /// Registers a new format provider.
- ///
- /// The format to register as a known format.
- public void AddImageFormat(IImageFormat format)
- {
- Guard.NotNull(format, nameof(format));
- Guard.NotNull(format.MimeTypes, nameof(format.MimeTypes));
- Guard.NotNull(format.FileExtensions, nameof(format.FileExtensions));
- this.imageFormats.Add(format);
- }
-
- ///
- /// For the specified file extensions type find the e .
- ///
- /// The extension to discover
- /// The if found otherwise null
- public IImageFormat FindFormatByFileExtension(string extension)
- {
- return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
- }
-
- ///
- /// For the specified mime type find the .
- ///
- /// The mime-type to discover
- /// The if found; otherwise null
- public IImageFormat FindFormatByMimeType(string mimeType)
- {
- return this.imageFormats.FirstOrDefault(x => x.MimeTypes.Contains(mimeType, StringComparer.OrdinalIgnoreCase));
- }
-
- ///
- /// Sets a specific image encoder as the encoder for a specific image format.
- ///
- /// The image format to register the encoder for.
- /// The encoder to use,
- public void SetEncoder(IImageFormat imageFormat, IImageEncoder encoder)
- {
- Guard.NotNull(imageFormat, nameof(imageFormat));
- Guard.NotNull(encoder, nameof(encoder));
- this.AddImageFormat(imageFormat);
- this.mimeTypeEncoders.AddOrUpdate(imageFormat, encoder, (s, e) => encoder);
- }
-
- ///
- /// Sets a specific image decoder as the decoder for a specific image format.
- ///
- /// The image format to register the encoder for.
- /// The decoder to use,
- public void SetDecoder(IImageFormat imageFormat, IImageDecoder decoder)
- {
- Guard.NotNull(imageFormat, nameof(imageFormat));
- Guard.NotNull(decoder, nameof(decoder));
- this.AddImageFormat(imageFormat);
- this.mimeTypeDecoders.AddOrUpdate(imageFormat, decoder, (s, e) => decoder);
- }
-
- ///
- /// Removes all the registered image format detectors.
- ///
- public void ClearImageFormatDetectors()
- {
- this.imageFormatDetectors = new ConcurrentBag();
- }
-
- ///
- /// Adds a new detector for detecting mime types.
- ///
- /// The detector to add
- public void AddImageFormatDetector(IImageFormatDetector detector)
- {
- Guard.NotNull(detector, nameof(detector));
- this.imageFormatDetectors.Add(detector);
- this.SetMaxHeaderSize();
- }
-
- ///
- /// For the specified mime type find the decoder.
- ///
- /// The format to discover
- /// The if found otherwise null
- public IImageDecoder FindDecoder(IImageFormat format)
- {
- Guard.NotNull(format, nameof(format));
- if (this.mimeTypeDecoders.TryGetValue(format, out IImageDecoder decoder))
- {
- return decoder;
- }
-
- return null;
- }
-
- ///
- /// For the specified mime type find the encoder.
- ///
- /// The format to discover
- /// The if found otherwise null
- public IImageEncoder FindEncoder(IImageFormat format)
- {
- Guard.NotNull(format, nameof(format));
- if (this.mimeTypeEncoders.TryGetValue(format, out IImageEncoder encoder))
- {
- return encoder;
- }
-
- return null;
- }
-
- ///
- /// Creates the default instance with the following s preregistered:
- ///
- ///
- ///
- ///
- ///
- /// The default configuration of
- internal static Configuration CreateDefaultInstance()
- {
- return new Configuration(
- new PngConfigurationModule(),
- new JpegConfigurationModule(),
- new GifConfigurationModule(),
- new BmpConfigurationModule());
- }
-
- ///
- /// Sets the max header size.
- ///
- private void SetMaxHeaderSize()
- {
- this.MaxHeaderSize = this.imageFormatDetectors.Max(x => x.HeaderSize);
- }
- }
-}
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using SixLabors.ImageSharp.Formats;
+using SixLabors.ImageSharp.Formats.Bmp;
+using SixLabors.ImageSharp.Formats.Gif;
+using SixLabors.ImageSharp.Formats.Jpeg;
+using SixLabors.ImageSharp.Formats.Png;
+using SixLabors.ImageSharp.IO;
+using SixLabors.ImageSharp.Memory;
+
+namespace SixLabors.ImageSharp
+{
+ ///
+ /// Provides initialization code which allows extending the library.
+ ///
+ public sealed class Configuration
+ {
+ ///
+ /// A lazily initialized configuration default instance.
+ ///
+ private static readonly Lazy Lazy = new Lazy(CreateDefaultInstance);
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Configuration()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A collection of configuration modules to register
+ public Configuration(params IConfigurationModule[] configurationModules)
+ {
+ if (configurationModules != null)
+ {
+ foreach (IConfigurationModule p in configurationModules)
+ {
+ p.Configure(this);
+ }
+ }
+ }
+
+ ///
+ /// Gets the default instance.
+ ///
+ public static Configuration Default { get; } = Lazy.Value;
+
+ ///
+ /// Gets the global parallel options for processing tasks in parallel.
+ ///
+ public ParallelOptions ParallelOptions { get; private set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
+
+ ///
+ /// Gets the currently registered s.
+ ///
+ public IEnumerable ImageFormats => this.ImageFormatsManager.ImageFormats;
+
+ ///
+ /// Gets or sets the position in a stream to use for reading when using a seekable stream as an image data source.
+ ///
+ public ReadOrigin ReadOrigin { get; set; } = ReadOrigin.Current;
+
+ ///
+ /// Gets or sets the that is currently in use.
+ ///
+ public ImageFormatManager ImageFormatsManager { get; set; } = new ImageFormatManager();
+
+ ///
+ /// Gets or sets the that is currently in use.
+ ///
+ public MemoryManager MemoryManager { get; set; } = ArrayPoolMemoryManager.CreateDefault();
+
+ ///
+ /// Gets the maximum header size of all the formats.
+ ///
+ internal int MaxHeaderSize => this.ImageFormatsManager.MaxHeaderSize;
+
+#if !NETSTANDARD1_1
+ ///
+ /// Gets or sets the filesystem helper for accessing the local file system.
+ ///
+ internal IFileSystem FileSystem { get; set; } = new LocalFileSystem();
+#endif
+
+ ///
+ /// Gets or sets the image operations provider factory.
+ ///
+ internal IImageProcessingContextFactory ImageOperationsProvider { get; set; } = new DefaultImageOperationsProviderFactory();
+
+ ///
+ /// Registers a new format provider.
+ ///
+ /// The configuration provider to call configure on.
+ public void Configure(IConfigurationModule configuration)
+ {
+ Guard.NotNull(configuration, nameof(configuration));
+ configuration.Configure(this);
+ }
+
+ ///
+ /// Creates a shallow copy of the
+ ///
+ /// A new configuration instance
+ public Configuration ShallowCopy()
+ {
+ return new Configuration
+ {
+ ParallelOptions = this.ParallelOptions,
+ ImageFormatsManager = this.ImageFormatsManager,
+ MemoryManager = this.MemoryManager,
+ ImageOperationsProvider = this.ImageOperationsProvider,
+ ReadOrigin = this.ReadOrigin,
+
+#if !NETSTANDARD1_1
+ FileSystem = this.FileSystem
+#endif
+ };
+ }
+
+ ///
+ /// Creates the default instance with the following s preregistered:
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// The default configuration of
+ internal static Configuration CreateDefaultInstance()
+ {
+ return new Configuration(
+ new PngConfigurationModule(),
+ new JpegConfigurationModule(),
+ new GifConfigurationModule(),
+ new BmpConfigurationModule());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/DefaultInternalImageProcessorContext.cs b/src/ImageSharp/DefaultInternalImageProcessorContext.cs
index 6e6feed84e..7ccc65e27e 100644
--- a/src/ImageSharp/DefaultInternalImageProcessorContext.cs
+++ b/src/ImageSharp/DefaultInternalImageProcessorContext.cs
@@ -1,7 +1,9 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
+using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;
@@ -34,6 +36,9 @@ namespace SixLabors.ImageSharp
}
}
+ ///
+ public MemoryManager MemoryManager => this.source.GetConfiguration().MemoryManager;
+
///
public Image Apply()
{
@@ -46,6 +51,9 @@ namespace SixLabors.ImageSharp
return this.destination;
}
+ ///
+ public Size GetCurrentSize() => this.GetCurrentBounds().Size;
+
///
public IImageProcessingContext ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
{
@@ -70,7 +78,12 @@ namespace SixLabors.ImageSharp
///
public IImageProcessingContext ApplyProcessor(IImageProcessor processor)
{
- return this.ApplyProcessor(processor, this.source.Bounds());
+ return this.ApplyProcessor(processor, this.GetCurrentBounds());
+ }
+
+ private Rectangle GetCurrentBounds()
+ {
+ return this.destination?.Bounds() ?? this.source.Bounds();
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuserBase.cs b/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuserBase.cs
index 46bafcc0cf..8f448198b0 100644
--- a/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuserBase.cs
+++ b/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuserBase.cs
@@ -70,22 +70,10 @@ namespace SixLabors.ImageSharp.Dithering.Base
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Dither(ImageFrame pixels, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY)
+ public void Dither(ImageFrame image, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY)
where TPixel : struct, IPixel
{
- this.Dither(pixels, source, transformed, x, y, minX, minY, maxX, maxY, true);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Dither(ImageFrame image, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY, bool replacePixel)
- where TPixel : struct, IPixel
- {
- if (replacePixel)
- {
- // Assign the transformed pixel to the array.
- image[x, y] = transformed;
- }
+ image[x, y] = transformed;
// Calculate the error
Vector4 error = source.ToVector4() - transformed.ToVector4();
diff --git a/src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs b/src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs
index c538d643c6..dabc4e6822 100644
--- a/src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs
+++ b/src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs
@@ -6,7 +6,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Dithering
{
///
- /// Encapsulates properties and methods required to perfom diffused error dithering on an image.
+ /// Encapsulates properties and methods required to perform diffused error dithering on an image.
///
public interface IErrorDiffuser
{
@@ -25,25 +25,5 @@ namespace SixLabors.ImageSharp.Dithering
/// The pixel format.
void Dither(ImageFrame image, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY)
where TPixel : struct, IPixel;
-
- ///
- /// Transforms the image applying the dither matrix. This method alters the input pixels array
- ///
- /// The image
- /// The source pixel
- /// The transformed pixel
- /// The column index.
- /// The row index.
- /// The minimum column value.
- /// The minimum row value.
- /// The maximum column value.
- /// The maximum row value.
- ///
- /// Whether to replace the pixel at the given coordinates with the transformed value.
- /// Generally this would be true for standard two-color dithering but when used in conjunction with color quantization this should be false.
- ///
- /// The pixel format.
- void Dither(ImageFrame image, TPixel source, TPixel transformed, int x, int y, int minX, int minY, int maxX, int maxY, bool replacePixel)
- where TPixel : struct, IPixel;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/ErrorDiffusion/KnownDiffusers.cs b/src/ImageSharp/Dithering/ErrorDiffusion/KnownDiffusers.cs
new file mode 100644
index 0000000000..c75530b8e7
--- /dev/null
+++ b/src/ImageSharp/Dithering/ErrorDiffusion/KnownDiffusers.cs
@@ -0,0 +1,56 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Dithering
+{
+ ///
+ /// Contains reusable static instances of known error diffusion algorithms
+ ///
+ public static class KnownDiffusers
+ {
+ ///
+ /// Gets the error diffuser that implements the Atkinson algorithm.
+ ///
+ public static IErrorDiffuser Atkinson { get; } = new AtkinsonDiffuser();
+
+ ///
+ /// Gets the error diffuser that implements the Burks algorithm.
+ ///
+ public static IErrorDiffuser Burks { get; } = new BurksDiffuser();
+
+ ///
+ /// Gets the error diffuser that implements the Floyd-Steinberg algorithm.
+ ///
+ public static IErrorDiffuser FloydSteinberg { get; } = new FloydSteinbergDiffuser();
+
+ ///
+ /// Gets the error diffuser that implements the Jarvis-Judice-Ninke algorithm.
+ ///
+ public static IErrorDiffuser JarvisJudiceNinke { get; } = new JarvisJudiceNinkeDiffuser();
+
+ ///
+ /// Gets the error diffuser that implements the Sierra-2 algorithm.
+ ///
+ public static IErrorDiffuser Sierra2 { get; } = new Sierra2Diffuser();
+
+ ///
+ /// Gets the error diffuser that implements the Sierra-3 algorithm.
+ ///
+ public static IErrorDiffuser Sierra3 { get; } = new Sierra3Diffuser();
+
+ ///
+ /// Gets the error diffuser that implements the Sierra-Lite algorithm.
+ ///
+ public static IErrorDiffuser SierraLite { get; } = new SierraLiteDiffuser();
+
+ ///
+ /// Gets the error diffuser that implements the Stevenson-Arce algorithm.
+ ///
+ public static IErrorDiffuser StevensonArce { get; } = new StevensonArceDiffuser();
+
+ ///
+ /// Gets the error diffuser that implements the Stucki algorithm.
+ ///
+ public static IErrorDiffuser Stucki { get; } = new StuckiDiffuser();
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/ErrorDiffusion/StevensonArceDiffuser.cs b/src/ImageSharp/Dithering/ErrorDiffusion/StevensonArceDiffuser.cs
new file mode 100644
index 0000000000..0f0338ac72
--- /dev/null
+++ b/src/ImageSharp/Dithering/ErrorDiffusion/StevensonArceDiffuser.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using SixLabors.ImageSharp.Dithering.Base;
+using SixLabors.ImageSharp.Memory;
+
+namespace SixLabors.ImageSharp.Dithering
+{
+ ///
+ /// Applies error diffusion based dithering using the Stevenson-Arce image dithering algorithm.
+ ///
+ public sealed class StevensonArceDiffuser : ErrorDiffuserBase
+ {
+ ///
+ /// The diffusion matrix
+ ///
+ private static readonly Fast2DArray StevensonArceMatrix =
+ new float[,]
+ {
+ { 0, 0, 0, 0, 0, 32, 0 },
+ { 12, 0, 26, 0, 30, 0, 16 },
+ { 0, 12, 0, 26, 0, 12, 0 },
+ { 5, 0, 12, 0, 12, 0, 5 }
+ };
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public StevensonArceDiffuser()
+ : base(StevensonArceMatrix, 200)
+ {
+ }
+ }
+}
diff --git a/src/ImageSharp/Dithering/Ordered/BayerDither.cs b/src/ImageSharp/Dithering/Ordered/BayerDither.cs
deleted file mode 100644
index 685dca5fe8..0000000000
--- a/src/ImageSharp/Dithering/Ordered/BayerDither.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using SixLabors.ImageSharp.Dithering.Base;
-using SixLabors.ImageSharp.Memory;
-
-namespace SixLabors.ImageSharp.Dithering
-{
- ///
- /// Applies error diffusion based dithering using the 4x4 Bayer dithering matrix.
- ///
- ///
- public sealed class BayerDither : OrderedDitherBase
- {
- ///
- /// The threshold matrix.
- /// This is calculated by multiplying each value in the original matrix by 16 and subtracting 1
- ///
- private static readonly Fast2DArray ThresholdMatrix =
- new byte[,]
- {
- { 15, 143, 47, 175 },
- { 207, 79, 239, 111 },
- { 63, 191, 31, 159 },
- { 255, 127, 223, 95 }
- };
-
- ///
- /// Initializes a new instance of the class.
- ///
- public BayerDither()
- : base(ThresholdMatrix)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/Ordered/BayerDither2x2.cs b/src/ImageSharp/Dithering/Ordered/BayerDither2x2.cs
new file mode 100644
index 0000000000..1d844c8a79
--- /dev/null
+++ b/src/ImageSharp/Dithering/Ordered/BayerDither2x2.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Dithering
+{
+ ///
+ /// Applies order dithering using the 2x2 Bayer dithering matrix.
+ ///
+ public sealed class BayerDither2x2 : OrderedDither
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BayerDither2x2()
+ : base(2)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/Ordered/BayerDither4x4.cs b/src/ImageSharp/Dithering/Ordered/BayerDither4x4.cs
new file mode 100644
index 0000000000..4e9f20beb9
--- /dev/null
+++ b/src/ImageSharp/Dithering/Ordered/BayerDither4x4.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Dithering
+{
+ ///
+ /// Applies order dithering using the 4x4 Bayer dithering matrix.
+ ///
+ public sealed class BayerDither4x4 : OrderedDither
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BayerDither4x4()
+ : base(4)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/Ordered/BayerDither8x8.cs b/src/ImageSharp/Dithering/Ordered/BayerDither8x8.cs
new file mode 100644
index 0000000000..3ff179a06a
--- /dev/null
+++ b/src/ImageSharp/Dithering/Ordered/BayerDither8x8.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Dithering
+{
+ ///
+ /// Applies order dithering using the 8x8 Bayer dithering matrix.
+ ///
+ public sealed class BayerDither8x8 : OrderedDither
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BayerDither8x8()
+ : base(8)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs b/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
index 689c9a85b4..339f2861d9 100644
--- a/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
+++ b/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
@@ -6,7 +6,7 @@ using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Dithering
{
///
- /// Encapsulates properties and methods required to perfom ordered dithering on an image.
+ /// Encapsulates properties and methods required to perform ordered dithering on an image.
///
public interface IOrderedDither
{
@@ -17,12 +17,11 @@ namespace SixLabors.ImageSharp.Dithering
/// The source pixel
/// The color to apply to the pixels above the threshold.
/// The color to apply to the pixels below the threshold.
- /// The to pack/unpack to.
- /// The component index to test the threshold against. Must range from 0 to 3.
+ /// The threshold to split the image. Must be between 0 and 1.
/// The column index.
/// The row index.
/// The pixel format.
- void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, ref Rgba32 rgba, int index, int x, int y)
+ void Dither