diff --git a/src/ImageSharp.Drawing/Brushes/IBrush.cs b/src/ImageSharp.Drawing/Brushes/IBrush.cs
index 9534c7a88..8cb731782 100644
--- a/src/ImageSharp.Drawing/Brushes/IBrush.cs
+++ b/src/ImageSharp.Drawing/Brushes/IBrush.cs
@@ -22,7 +22,7 @@ namespace ImageSharp.Drawing
///
/// Creates the applicator for this brush.
///
- /// The pixel source.
+ /// The source image.
/// The region the brush will be applied to.
/// The graphic options
///
@@ -32,6 +32,6 @@ namespace ImageSharp.Drawing
/// The when being applied to things like shapes would usually be the
/// bounding box of the shape not necessarily the bounds of the whole image
///
- BrushApplicator CreateApplicator(PixelAccessor pixelSource, RectangleF region, GraphicsOptions options);
+ BrushApplicator CreateApplicator(ImageBase source, RectangleF region, GraphicsOptions options);
}
}
\ 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 6f851e5c3..59dbd3926 100644
--- a/src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Brushes/ImageBrush{TPixel}.cs
@@ -6,7 +6,6 @@
namespace ImageSharp.Drawing.Brushes
{
using System;
- using System.Numerics;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
@@ -22,21 +21,21 @@ namespace ImageSharp.Drawing.Brushes
///
/// The image to paint.
///
- private readonly IImageBase image;
+ private readonly ImageBase image;
///
/// Initializes a new instance of the class.
///
/// The image.
- public ImageBrush(IImageBase image)
+ public ImageBrush(ImageBase image)
{
this.image = image;
}
///
- public BrushApplicator CreateApplicator(PixelAccessor sourcePixels, RectangleF region, GraphicsOptions options)
+ public BrushApplicator CreateApplicator(ImageBase source, RectangleF region, GraphicsOptions options)
{
- return new ImageBrushApplicator(sourcePixels, this.image, region, options);
+ return new ImageBrushApplicator(source, this.image, region, options);
}
///
@@ -45,9 +44,9 @@ namespace ImageSharp.Drawing.Brushes
private class ImageBrushApplicator : BrushApplicator
{
///
- /// The source pixel accessor.
+ /// The source image.
///
- private readonly PixelAccessor source;
+ private readonly ImageBase source;
///
/// The y-length.
@@ -72,20 +71,14 @@ namespace ImageSharp.Drawing.Brushes
///
/// Initializes a new instance of the class.
///
- ///
- /// The image.
- ///
- ///
- /// The region.
- ///
+ /// The target image.
+ /// The image.
+ /// The region.
/// The options
- ///
- /// The sourcePixels.
- ///
- public ImageBrushApplicator(PixelAccessor sourcePixels, IImageBase image, RectangleF region, GraphicsOptions options)
- : base(sourcePixels, options)
+ public ImageBrushApplicator(ImageBase target, ImageBase image, RectangleF region, GraphicsOptions options)
+ : base(target, options)
{
- this.source = image.Lock();
+ this.source = image;
this.xLength = image.Width;
this.yLength = image.Height;
this.offsetY = (int)MathF.Max(MathF.Floor(region.Top), 0);
@@ -119,9 +112,9 @@ namespace ImageSharp.Drawing.Brushes
///
internal override void Apply(Span scanline, int x, int y)
{
- // create a span for colors
- using (Buffer amountBuffer = new Buffer(scanline.Length))
- using (Buffer overlay = new Buffer(scanline.Length))
+ // Create a span for colors
+ using (var amountBuffer = new Buffer(scanline.Length))
+ using (var overlay = new Buffer(scanline.Length))
{
int sourceY = (y - this.offsetY) % this.yLength;
int offsetX = x - this.offsetX;
diff --git a/src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs b/src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs
index 90990e54a..5dd57bda6 100644
--- a/src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Brushes/PatternBrush{TPixel}.cs
@@ -62,8 +62,8 @@ namespace ImageSharp.Drawing.Brushes
/// The pattern.
internal PatternBrush(TPixel foreColor, TPixel backColor, Fast2DArray pattern)
{
- Vector4 foreColorVector = foreColor.ToVector4();
- Vector4 backColorVector = backColor.ToVector4();
+ var foreColorVector = foreColor.ToVector4();
+ var backColorVector = backColor.ToVector4();
this.pattern = new Fast2DArray(pattern.Width, pattern.Height);
this.patternVector = new Fast2DArray(pattern.Width, pattern.Height);
for (int i = 0; i < pattern.Data.Length; i++)
@@ -92,9 +92,9 @@ namespace ImageSharp.Drawing.Brushes
}
///
- public BrushApplicator CreateApplicator(PixelAccessor sourcePixels, RectangleF region, GraphicsOptions options)
+ public BrushApplicator CreateApplicator(ImageBase source, RectangleF region, GraphicsOptions options)
{
- return new PatternBrushApplicator(sourcePixels, this.pattern, this.patternVector, options);
+ return new PatternBrushApplicator(source, this.pattern, this.patternVector, options);
}
///
@@ -111,12 +111,12 @@ namespace ImageSharp.Drawing.Brushes
///
/// Initializes a new instance of the class.
///
- /// The sourcePixels.
+ /// The source image.
/// The pattern.
/// The patternVector.
/// The options
- public PatternBrushApplicator(PixelAccessor sourcePixels, Fast2DArray pattern, Fast2DArray patternVector, GraphicsOptions options)
- : base(sourcePixels, options)
+ public PatternBrushApplicator(ImageBase source, Fast2DArray pattern, Fast2DArray patternVector, GraphicsOptions options)
+ : base(source, options)
{
this.pattern = pattern;
this.patternVector = patternVector;
@@ -152,8 +152,8 @@ namespace ImageSharp.Drawing.Brushes
internal override void Apply(Span scanline, int x, int y)
{
int patternY = y % this.pattern.Height;
- using (Buffer amountBuffer = new Buffer(scanline.Length))
- using (Buffer overlay = new Buffer(scanline.Length))
+ using (var amountBuffer = new Buffer(scanline.Length))
+ using (var overlay = new Buffer(scanline.Length))
{
for (int i = 0; i < scanline.Length; i++)
{
diff --git a/src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs b/src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
index 29629324a..29c625d7f 100644
--- a/src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
+++ b/src/ImageSharp.Drawing/Brushes/Processors/BrushApplicator.cs
@@ -6,7 +6,6 @@
namespace ImageSharp.Drawing.Processors
{
using System;
- using System.Numerics;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
@@ -24,7 +23,7 @@ namespace ImageSharp.Drawing.Processors
///
/// The target.
/// The options.
- internal BrushApplicator(PixelAccessor target, GraphicsOptions options)
+ internal BrushApplicator(ImageBase target, GraphicsOptions options)
{
this.Target = target;
@@ -41,7 +40,7 @@ namespace ImageSharp.Drawing.Processors
///
/// Gets the destinaion
///
- protected PixelAccessor Target { get; }
+ protected ImageBase Target { get; }
///
/// Gets the blend percentage
@@ -68,8 +67,8 @@ namespace ImageSharp.Drawing.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 (Buffer amountBuffer = new Buffer(scanline.Length))
- using (Buffer overlay = new Buffer(scanline.Length))
+ using (var amountBuffer = new Buffer(scanline.Length))
+ using (var overlay = new Buffer(scanline.Length))
{
for (int i = 0; i < scanline.Length; i++)
{
diff --git a/src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs b/src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs
index 64b91e384..96d824b2f 100644
--- a/src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Brushes/RecolorBrush{TPixel}.cs
@@ -57,9 +57,9 @@ namespace ImageSharp.Drawing.Brushes
public TPixel TargeTPixel { get; }
///
- public BrushApplicator CreateApplicator(PixelAccessor sourcePixels, RectangleF region, GraphicsOptions options)
+ public BrushApplicator CreateApplicator(ImageBase source, RectangleF region, GraphicsOptions options)
{
- return new RecolorBrushApplicator(sourcePixels, this.SourceColor, this.TargeTPixel, this.Threshold, options);
+ return new RecolorBrushApplicator(source, this.SourceColor, this.TargeTPixel, this.Threshold, options);
}
///
@@ -87,22 +87,22 @@ namespace ImageSharp.Drawing.Brushes
///
/// Initializes a new instance of the class.
///
- /// The source pixels.
+ /// The source image.
/// Color of the source.
/// Color of the target.
/// The threshold .
/// The options
- public RecolorBrushApplicator(PixelAccessor sourcePixels, TPixel sourceColor, TPixel targetColor, float threshold, GraphicsOptions options)
- : base(sourcePixels, options)
+ public RecolorBrushApplicator(ImageBase source, TPixel sourceColor, TPixel targetColor, float threshold, GraphicsOptions options)
+ : base(source, options)
{
this.sourceColor = sourceColor.ToVector4();
this.targetColor = targetColor.ToVector4();
this.targetColorPixel = targetColor;
- // Lets hack a min max extreams for a color space by letteing the IPackedPixel clamp our values to something in the correct spaces :)
- TPixel maxColor = default(TPixel);
+ // Lets hack a min max extreams for a color space by letting the IPackedPixel clamp our values to something in the correct spaces :)
+ var maxColor = default(TPixel);
maxColor.PackFromVector4(new Vector4(float.MaxValue));
- TPixel minColor = default(TPixel);
+ var minColor = default(TPixel);
minColor.PackFromVector4(new Vector4(float.MinValue));
this.threshold = Vector4.DistanceSquared(maxColor.ToVector4(), minColor.ToVector4()) * threshold;
}
@@ -121,7 +121,7 @@ namespace ImageSharp.Drawing.Brushes
{
// Offset the requested pixel by the value in the rectangle (the shapes position)
TPixel result = this.Target[x, y];
- Vector4 background = result.ToVector4();
+ var background = result.ToVector4();
float distance = Vector4.DistanceSquared(background, this.sourceColor);
if (distance <= this.threshold)
{
@@ -144,8 +144,8 @@ namespace ImageSharp.Drawing.Brushes
///
internal override void Apply(Span scanline, int x, int y)
{
- using (Buffer amountBuffer = new Buffer(scanline.Length))
- using (Buffer overlay = new Buffer(scanline.Length))
+ using (var amountBuffer = new Buffer(scanline.Length))
+ using (var overlay = new Buffer(scanline.Length))
{
for (int i = 0; i < scanline.Length; i++)
{
diff --git a/src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs b/src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs
index 28f7b0e45..453b4d29e 100644
--- a/src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Brushes/SolidBrush{TPixel}.cs
@@ -42,9 +42,9 @@ namespace ImageSharp.Drawing.Brushes
public TPixel Color => this.color;
///
- public BrushApplicator CreateApplicator(PixelAccessor sourcePixels, RectangleF region, GraphicsOptions options)
+ public BrushApplicator CreateApplicator(ImageBase source, RectangleF region, GraphicsOptions options)
{
- return new SolidBrushApplicator(sourcePixels, this.color, options);
+ return new SolidBrushApplicator(source, this.color, options);
}
///
@@ -55,13 +55,13 @@ namespace ImageSharp.Drawing.Brushes
///
/// Initializes a new instance of the class.
///
+ /// The source image.
/// The color.
/// The options
- /// The sourcePixels.
- public SolidBrushApplicator(PixelAccessor sourcePixels, TPixel color, GraphicsOptions options)
- : base(sourcePixels, options)
+ public SolidBrushApplicator(ImageBase source, TPixel color, GraphicsOptions options)
+ : base(source, options)
{
- this.Colors = new Buffer(sourcePixels.Width);
+ this.Colors = new Buffer(source.Width);
for (int i = 0; i < this.Colors.Length; i++)
{
this.Colors[i] = color;
@@ -94,7 +94,7 @@ namespace ImageSharp.Drawing.Brushes
{
Span destinationRow = this.Target.GetRowSpan(x, y).Slice(0, scanline.Length);
- using (Buffer amountBuffer = new Buffer(scanline.Length))
+ using (var amountBuffer = new Buffer(scanline.Length))
{
for (int i = 0; i < scanline.Length; i++)
{
diff --git a/src/ImageSharp.Drawing/Pens/IPen.cs b/src/ImageSharp.Drawing/Pens/IPen.cs
index d488dbfb0..81d273091 100644
--- a/src/ImageSharp.Drawing/Pens/IPen.cs
+++ b/src/ImageSharp.Drawing/Pens/IPen.cs
@@ -18,7 +18,7 @@ namespace ImageSharp.Drawing.Pens
///
/// Creates the applicator for applying this pen to an Image
///
- /// The pixel source.
+ /// The source image.
/// The region the pen will be applied to.
/// The currently active graphic options.
///
@@ -27,6 +27,6 @@ namespace ImageSharp.Drawing.Pens
///
/// The when being applied to things like shapes would usually be the bounding box of the shape not necessarily the shape of the whole image.
///
- PenApplicator CreateApplicator(PixelAccessor pixelSource, RectangleF region, GraphicsOptions options);
+ PenApplicator CreateApplicator(ImageBase source, RectangleF region, GraphicsOptions options);
}
}
diff --git a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs
index 1da50e0d6..53a3c8c99 100644
--- a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs
+++ b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs
@@ -101,7 +101,7 @@ namespace ImageSharp.Drawing.Pens
///
/// Creates the applicator for applying this pen to an Image
///
- /// The source pixels.
+ /// The source image.
/// The region the pen will be applied to.
/// The Graphics options
///
@@ -111,16 +111,16 @@ namespace ImageSharp.Drawing.Pens
/// The when being applied to things like shapes would ussually be the
/// bounding box of the shape not necorserrally the shape of the whole image
///
- public PenApplicator CreateApplicator(PixelAccessor sourcePixels, RectangleF region, GraphicsOptions options)
+ public PenApplicator CreateApplicator(ImageBase source, RectangleF region, GraphicsOptions options)
{
if (this.pattern == null || this.pattern.Length < 2)
{
// if there is only one item in the pattern then 100% of it will
// be solid so use the quicker applicator
- return new SolidPenApplicator(sourcePixels, this.Brush, region, this.Width, options);
+ return new SolidPenApplicator(source, this.Brush, region, this.Width, options);
}
- return new PatternPenApplicator(sourcePixels, this.Brush, region, this.Width, this.pattern, options);
+ return new PatternPenApplicator(source, this.Brush, region, this.Width, this.pattern, options);
}
private class SolidPenApplicator : PenApplicator
@@ -128,7 +128,7 @@ namespace ImageSharp.Drawing.Pens
private readonly BrushApplicator brush;
private readonly float halfWidth;
- public SolidPenApplicator(PixelAccessor sourcePixels, IBrush brush, RectangleF region, float width, GraphicsOptions options)
+ public SolidPenApplicator(ImageBase sourcePixels, IBrush brush, RectangleF region, float width, GraphicsOptions options)
{
this.brush = brush.CreateApplicator(sourcePixels, region, options);
this.halfWidth = width / 2;
@@ -147,7 +147,7 @@ namespace ImageSharp.Drawing.Pens
public override ColoredPointInfo GetColor(int x, int y, PointInfo info)
{
- ColoredPointInfo result = default(ColoredPointInfo);
+ var result = default(ColoredPointInfo);
result.Color = this.brush[x, y];
if (info.DistanceFromPath < this.halfWidth)
@@ -171,9 +171,9 @@ namespace ImageSharp.Drawing.Pens
private readonly float[] pattern;
private readonly float totalLength;
- public PatternPenApplicator(PixelAccessor sourcePixels, IBrush brush, RectangleF region, float width, float[] pattern, GraphicsOptions options)
+ public PatternPenApplicator(ImageBase source, IBrush brush, RectangleF region, float width, float[] pattern, GraphicsOptions options)
{
- this.brush = brush.CreateApplicator(sourcePixels, region, options);
+ this.brush = brush.CreateApplicator(source, region, options);
this.halfWidth = width / 2;
this.totalLength = 0;
@@ -200,7 +200,7 @@ namespace ImageSharp.Drawing.Pens
public override ColoredPointInfo GetColor(int x, int y, PointInfo info)
{
- ColoredPointInfo infoResult = default(ColoredPointInfo);
+ var infoResult = default(ColoredPointInfo);
infoResult.DistanceFromElement = float.MaxValue; // is really outside the element
float length = info.DistanceAlongPath % this.totalLength;
diff --git a/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs b/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs
index d1332c435..860c4c4f0 100644
--- a/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs
+++ b/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs
@@ -56,8 +56,7 @@ namespace ImageSharp.Drawing.Processors
///
protected override void OnApply(ImageBase source, Rectangle sourceRectangle)
{
- using (PixelAccessor sourcePixels = source.Lock())
- using (PenApplicator applicator = this.Pen.CreateApplicator(sourcePixels, this.Path.Bounds, this.Options))
+ using (PenApplicator applicator = this.Pen.CreateApplicator(source, this.Path.Bounds, this.Options))
{
Rectangle rect = RectangleF.Ceiling(applicator.RequiredRegion);
@@ -99,8 +98,8 @@ namespace ImageSharp.Drawing.Processors
{
int offsetY = y - polyStartY;
- using (Buffer amount = new Buffer(width))
- using (Buffer colors = new Buffer(width))
+ using (var amount = new Buffer(width))
+ using (var colors = new Buffer(width))
{
for (int i = 0; i < width; i++)
{
@@ -112,7 +111,7 @@ namespace ImageSharp.Drawing.Processors
colors[i] = color.Color;
}
- Span destination = sourcePixels.GetRowSpan(offsetY).Slice(minX - startX, width);
+ Span destination = source.GetRowSpan(offsetY).Slice(minX - startX, width);
blender.Blend(destination, destination, colors, amount);
}
});
diff --git a/src/ImageSharp.Drawing/Processors/FillProcessor.cs b/src/ImageSharp.Drawing/Processors/FillProcessor.cs
index fa6f48156..8c7cd4e8c 100644
--- a/src/ImageSharp.Drawing/Processors/FillProcessor.cs
+++ b/src/ImageSharp.Drawing/Processors/FillProcessor.cs
@@ -66,12 +66,11 @@ namespace ImageSharp.Drawing.Processors
int width = maxX - minX;
- // we could possibly do some optermising by having knowledge about the individual brushes operate
+ // We could possibly do some optimization by having knowledge about the individual brushes operate
// for example If brush is SolidBrush then we could just get the color upfront
// and skip using the IBrushApplicator?.
- using (PixelAccessor sourcePixels = source.Lock())
- using (Buffer amount = new Buffer(width))
- using (BrushApplicator applicator = this.brush.CreateApplicator(sourcePixels, sourceRectangle, this.options))
+ using (var amount = new Buffer(width))
+ using (BrushApplicator applicator = this.brush.CreateApplicator(source, sourceRectangle, this.options))
{
for (int i = 0; i < width; i++)
{
diff --git a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
index a57be3a5a..ae828e112 100644
--- a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
+++ b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
@@ -7,6 +7,7 @@ namespace ImageSharp.Drawing.Processors
{
using System;
using System.Buffers;
+ using System.Runtime.CompilerServices;
using Drawing;
using ImageSharp.Memory;
@@ -89,12 +90,11 @@ namespace ImageSharp.Drawing.Processors
}
}
- using (PixelAccessor sourcePixels = source.Lock())
- using (BrushApplicator applicator = this.Brush.CreateApplicator(sourcePixels, rect, this.Options))
+ using (BrushApplicator applicator = this.Brush.CreateApplicator(source, rect, this.Options))
{
float[] buffer = arrayPool.Rent(maxIntersections);
int scanlineWidth = maxX - minX;
- using (Buffer scanline = new Buffer(scanlineWidth))
+ using (var scanline = new Buffer(scanlineWidth))
{
try
{
@@ -193,6 +193,7 @@ namespace ImageSharp.Drawing.Processors
}
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Swap(float[] data, int left, int right)
{
float tmp = data[left];
diff --git a/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs b/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs
index 7a5fabdb3..0c4192a87 100644
--- a/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs
+++ b/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs
@@ -71,7 +71,7 @@ namespace ImageSharp.Dithering
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Dither(PixelAccessor pixels, TPixel source, TPixel transformed, int x, int y, int width, int height)
+ public void Dither(ImageBase pixels, TPixel source, TPixel transformed, int x, int y, int width, int height)
where TPixel : struct, IPixel
{
this.Dither(pixels, source, transformed, x, y, width, height, true);
@@ -79,13 +79,13 @@ namespace ImageSharp.Dithering
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void Dither(PixelAccessor pixels, TPixel source, TPixel transformed, int x, int y, int width, int height, bool replacePixel)
+ public void Dither(ImageBase image, TPixel source, TPixel transformed, int x, int y, int width, int height, bool replacePixel)
where TPixel : struct, IPixel
{
if (replacePixel)
{
// Assign the transformed pixel to the array.
- pixels[x, y] = transformed;
+ image[x, y] = transformed;
}
// Calculate the error
@@ -111,14 +111,14 @@ namespace ImageSharp.Dithering
continue;
}
- Vector4 coefficientVector = new Vector4(coefficient);
- Vector4 offsetColor = pixels[matrixX, matrixY].ToVector4();
+ var coefficientVector = new Vector4(coefficient);
+ var offsetColor = image[matrixX, matrixY].ToVector4();
Vector4 result = ((error * coefficientVector) / this.divisorVector) + offsetColor;
result.W = offsetColor.W;
- TPixel packed = default(TPixel);
+ var packed = default(TPixel);
packed.PackFromVector4(result);
- pixels[matrixX, matrixY] = packed;
+ image[matrixX, matrixY] = packed;
}
}
}
diff --git a/src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs b/src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs
index f49e7e62d..bc785e897 100644
--- a/src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs
+++ b/src/ImageSharp/Dithering/ErrorDiffusion/IErrorDiffuser.cs
@@ -15,7 +15,7 @@ namespace ImageSharp.Dithering
///
/// Transforms the image applying the dither matrix. This method alters the input pixels array
///
- /// The pixel accessor
+ /// The image
/// The source pixel
/// The transformed pixel
/// The column index.
@@ -23,13 +23,13 @@ namespace ImageSharp.Dithering
/// The image width.
/// The image height.
/// The pixel format.
- void Dither(PixelAccessor pixels, TPixel source, TPixel transformed, int x, int y, int width, int height)
+ void Dither(ImageBase image, TPixel source, TPixel transformed, int x, int y, int width, int height)
where TPixel : struct, IPixel;
///
/// Transforms the image applying the dither matrix. This method alters the input pixels array
///
- /// The pixel accessor
+ /// The image
/// The source pixel
/// The transformed pixel
/// The column index.
@@ -41,7 +41,7 @@ namespace ImageSharp.Dithering
/// 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(PixelAccessor pixels, TPixel source, TPixel transformed, int x, int y, int width, int height, bool replacePixel)
+ void Dither(ImageBase image, TPixel source, TPixel transformed, int x, int y, int width, int height, bool replacePixel)
where TPixel : struct, IPixel;
}
}
diff --git a/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs b/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
index 3f7cf4988..c69cddefe 100644
--- a/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
+++ b/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
@@ -15,7 +15,7 @@ namespace ImageSharp.Dithering
///
/// Transforms the image applying the dither matrix. This method alters the input pixels array
///
- /// The pixel accessor
+ /// The image
/// The source pixel
/// The color to apply to the pixels above the threshold.
/// The color to apply to the pixels below the threshold.
@@ -26,7 +26,7 @@ namespace ImageSharp.Dithering
/// The image width.
/// The image height.
/// The pixel format.
- void Dither(PixelAccessor pixels, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y, int width, int height)
+ void Dither(ImageBase image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y, int width, int height)
where TPixel : struct, IPixel;
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/Ordered/OrderedDither4x4.cs b/src/ImageSharp/Dithering/Ordered/OrderedDither4x4.cs
index 48d6c3f6a..a180888f7 100644
--- a/src/ImageSharp/Dithering/Ordered/OrderedDither4x4.cs
+++ b/src/ImageSharp/Dithering/Ordered/OrderedDither4x4.cs
@@ -28,14 +28,14 @@ namespace ImageSharp.Dithering.Ordered
}
///
- public void Dither(PixelAccessor pixels, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y, int width, int height)
+ public void Dither(ImageBase image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y, int width, int height)
where TPixel : struct, IPixel
{
// TODO: This doesn't really cut it for me.
- // I'd rather be using float but we need to add some sort of movalization vector methods to all IPixel implementations
+ // I'd rather be using float but we need to add some sort of normalization vector methods to all IPixel implementations
// before we can do that as the vectors all cover different ranges.
source.ToXyzwBytes(bytes, 0);
- pixels[x, y] = this.matrix[y % 3, x % 3] >= bytes[index] ? lower : upper;
+ image[x, y] = this.matrix[y % 3, x % 3] >= bytes[index] ? lower : upper;
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Image/IImageBase{TPixel}.cs b/src/ImageSharp/Image/IImageBase{TPixel}.cs
index 08d25709b..f0ab5b033 100644
--- a/src/ImageSharp/Image/IImageBase{TPixel}.cs
+++ b/src/ImageSharp/Image/IImageBase{TPixel}.cs
@@ -21,14 +21,5 @@ namespace ImageSharp
/// of the array for calculations. Use Width * Height.
///
TPixel[] Pixels { get; }
-
- ///
- /// Locks the image providing access to the pixels.
- ///
- /// It is imperative that the accessor is correctly disposed off after use.
- ///
- ///
- /// The
- PixelAccessor Lock();
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Image/ImageBase{TPixel}.cs b/src/ImageSharp/Image/ImageBase{TPixel}.cs
index 4fd9d26cb..f7b294cf0 100644
--- a/src/ImageSharp/Image/ImageBase{TPixel}.cs
+++ b/src/ImageSharp/Image/ImageBase{TPixel}.cs
@@ -7,6 +7,7 @@ namespace ImageSharp
{
using System;
using System.Diagnostics;
+ using System.Runtime.CompilerServices;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
@@ -36,6 +37,11 @@ namespace ImageSharp
///
private TPixel[] pixelBuffer;
+ ///
+ /// The span representing the pixel buffer
+ ///
+ private Span span;
+
///
/// A value indicating whether this instance of the given entity has been disposed.
///
@@ -129,6 +135,67 @@ namespace ImageSharp
///
public Configuration Configuration { get; private set; }
+ ///
+ /// Gets or sets the pixel at the specified position.
+ ///
+ /// The x-coordinate of the pixel. Must be greater than or equal to zero and less than the width of the image.
+ /// The y-coordinate of the pixel. Must be greater than or equal to zero and less than the height of the image.
+ /// The at the specified position.
+ public TPixel this[int x, int y]
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ this.CheckCoordinates(x, y);
+ return this.pixelBuffer[(y * this.Width) + x];
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ set
+ {
+ this.CheckCoordinates(x, y);
+ this.pixelBuffer[(y * this.Width) + x] = value;
+ }
+ }
+
+ ///
+ /// Gets a reference to the pixel at the specified position.
+ ///
+ /// The x-coordinate of the pixel. Must be greater than or equal to zero and less than the width of the image.
+ /// The y-coordinate of the pixel. Must be greater than or equal to zero and less than the height of the image.
+ /// The at the specified position.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public ref TPixel GetPixelReference(int x, int y)
+ {
+ this.CheckCoordinates(x, y);
+ return ref this.pixelBuffer[(y * this.Width) + x];
+ }
+
+ ///
+ /// Gets a representing the row 'y' beginning from the the first pixel on that row.
+ ///
+ /// The y-coordinate of the pixel row. Must be greater than or equal to zero and less than the height of the image.
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Span GetRowSpan(int y)
+ {
+ this.CheckCoordinates(y);
+ return this.span.Slice(y * this.Width, this.Width);
+ }
+
+ ///
+ /// Gets a to the row 'y' beginning from the pixel at 'x'.
+ ///
+ /// The x coordinate (position in the row)
+ /// The y (row) coordinate
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Span GetRowSpan(int x, int y)
+ {
+ this.CheckCoordinates(x, y);
+ return this.span.Slice((y * this.Width) + x, this.Width - x);
+ }
+
///
/// Applies the processor.
///
@@ -152,8 +219,14 @@ namespace ImageSharp
GC.SuppressFinalize(this);
}
- ///
- public PixelAccessor Lock()
+ ///
+ /// Locks the image providing access to the pixels.
+ ///
+ /// It is imperative that the accessor is correctly disposed off after use.
+ ///
+ ///
+ /// The
+ internal PixelAccessor Lock()
{
return new PixelAccessor(this);
}
@@ -174,6 +247,7 @@ namespace ImageSharp
this.Width = newWidth;
this.Height = newHeight;
this.pixelBuffer = newPixels;
+ this.span = new Span(this.pixelBuffer);
}
///
@@ -225,6 +299,7 @@ namespace ImageSharp
private void RentPixels()
{
this.pixelBuffer = PixelDataPool.Rent(this.Width * this.Height);
+ this.span = new Span(this.pixelBuffer);
}
///
@@ -234,6 +309,7 @@ namespace ImageSharp
{
PixelDataPool.Return(this.pixelBuffer);
this.pixelBuffer = null;
+ this.span = null;
}
///
@@ -243,5 +319,43 @@ namespace ImageSharp
{
Array.Clear(this.pixelBuffer, 0, this.Width * this.Height);
}
+
+ ///
+ /// Checks the coordinates to ensure they are within bounds.
+ ///
+ /// The y-coordinate of the pixel. Must be greater than zero and less than the height of the image.
+ ///
+ /// Thrown if the coordinates are not within the bounds of the image.
+ ///
+ [Conditional("DEBUG")]
+ private void CheckCoordinates(int y)
+ {
+ if (y < 0 || y >= this.Height)
+ {
+ throw new ArgumentOutOfRangeException(nameof(y), y, $"{y} is outwith the image bounds.");
+ }
+ }
+
+ ///
+ /// Checks the coordinates to ensure they are within bounds.
+ ///
+ /// The x-coordinate of the pixel. Must be greater than zero and less than the width of the image.
+ /// The y-coordinate of the pixel. Must be greater than zero and less than the height of the image.
+ ///
+ /// Thrown if the coordinates are not within the bounds of the image.
+ ///
+ [Conditional("DEBUG")]
+ private void CheckCoordinates(int x, int y)
+ {
+ if (x < 0 || x >= this.Width)
+ {
+ throw new ArgumentOutOfRangeException(nameof(x), x, $"{x} is outwith the image bounds.");
+ }
+
+ if (y < 0 || y >= this.Height)
+ {
+ throw new ArgumentOutOfRangeException(nameof(y), y, $"{y} is outwith the image bounds.");
+ }
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs
index a54c03b63..240e65c82 100644
--- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs
+++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs
@@ -17,7 +17,7 @@ namespace ImageSharp
/// Provides per-pixel access to generic pixels.
///
/// The pixel format.
- public sealed class PixelAccessor : IDisposable, IBuffer2D
+ internal sealed class PixelAccessor : IDisposable, IBuffer2D
where TPixel : struct, IPixel
{
///
@@ -128,12 +128,14 @@ namespace ImageSharp
/// The at the specified position.
public TPixel this[int x, int y]
{
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
this.CheckCoordinates(x, y);
return this.PixelArray[(y * this.Width) + x];
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.CheckCoordinates(x, y);
diff --git a/src/ImageSharp/Memory/Buffer2DExtensions.cs b/src/ImageSharp/Memory/Buffer2DExtensions.cs
index 51e558281..046bfd81f 100644
--- a/src/ImageSharp/Memory/Buffer2DExtensions.cs
+++ b/src/ImageSharp/Memory/Buffer2DExtensions.cs
@@ -29,7 +29,7 @@ namespace ImageSharp.Memory
}
///
- /// Gets a to the row 'y' beginning from the pixel at 'x'.
+ /// Gets a to the row 'y' beginning from the pixel at the first pixel on that row.
///
/// The buffer
/// The y (row) coordinate
diff --git a/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs
index af2d9f760..cb6f2fce4 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs
@@ -85,18 +85,15 @@ namespace ImageSharp.Processing.Processors
startY = 0;
}
- using (PixelAccessor sourcePixels = source.Lock())
+ for (int y = minY; y < maxY; y++)
{
- for (int y = minY; y < maxY; y++)
+ int offsetY = y - startY;
+ for (int x = minX; x < maxX; x++)
{
- int offsetY = y - startY;
- for (int x = minX; x < maxX; x++)
- {
- int offsetX = x - startX;
- TPixel sourceColor = sourcePixels[offsetX, offsetY];
- TPixel transformedColor = sourceColor.ToVector4().X >= this.Threshold ? this.UpperColor : this.LowerColor;
- this.Diffuser.Dither(sourcePixels, sourceColor, transformedColor, offsetX, offsetY, maxX, maxY);
- }
+ int offsetX = x - startX;
+ TPixel sourceColor = source[offsetX, offsetY];
+ TPixel transformedColor = sourceColor.ToVector4().X >= this.Threshold ? this.UpperColor : this.LowerColor;
+ this.Diffuser.Dither(source, sourceColor, transformedColor, offsetX, offsetY, maxX, maxY);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
index c4d71d9af..1bdb4d53b 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
@@ -93,21 +93,16 @@ namespace ImageSharp.Processing.Processors
startY = 0;
}
- using (PixelAccessor sourcePixels = source.Lock())
+ byte[] bytes = new byte[4];
+ for (int y = minY; y < maxY; y++)
{
- for (int y = minY; y < maxY; y++)
- {
- int offsetY = y - startY;
- byte[] bytes = ArrayPool.Shared.Rent(4);
-
- for (int x = minX; x < maxX; x++)
- {
- int offsetX = x - startX;
- TPixel sourceColor = sourcePixels[offsetX, offsetY];
- this.Dither.Dither(sourcePixels, sourceColor, this.UpperColor, this.LowerColor, bytes, this.Index, offsetX, offsetY, maxX, maxY);
- }
+ int offsetY = y - startY;
- ArrayPool.Shared.Return(bytes);
+ for (int x = minX; x < maxX; x++)
+ {
+ int offsetX = x - startX;
+ TPixel sourceColor = source[offsetX, offsetY];
+ this.Dither.Dither(source, sourceColor, this.UpperColor, this.LowerColor, bytes, this.Index, offsetX, offsetY, maxX, maxY);
}
}
}
diff --git a/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs
index 40bce74c3..f41272900 100644
--- a/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs
+++ b/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs
@@ -66,7 +66,7 @@ namespace ImageSharp.Quantizers
}
///
- protected override void SecondPass(PixelAccessor source, byte[] output, int width, int height)
+ protected override void SecondPass(ImageBase source, byte[] output, int width, int height)
{
// Load up the values for the first pixel. We can use these to speed up the second
// pass of the algorithm by avoiding transforming rows of identical color.
@@ -490,7 +490,7 @@ namespace ImageSharp.Quantizers
byte b = (this.blue / this.pixelCount).ToByte();
// And set the color of the palette entry
- TPixel pixel = default(TPixel);
+ var pixel = default(TPixel);
pixel.PackFromBytes(r, g, b, 255);
palette[index] = pixel;
diff --git a/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs
index 7e07da6c3..52d3f320d 100644
--- a/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs
+++ b/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs
@@ -51,7 +51,7 @@ namespace ImageSharp.Quantizers
for (int i = 0; i < constants.Length; i++)
{
constants[i].ToXyzwBytes(this.pixelBuffer, 0);
- TPixel packed = default(TPixel);
+ var packed = default(TPixel);
packed.PackFromBytes(this.pixelBuffer[0], this.pixelBuffer[1], this.pixelBuffer[2], this.pixelBuffer[3]);
safe[i] = packed;
}
@@ -72,7 +72,7 @@ namespace ImageSharp.Quantizers
}
///
- protected override void SecondPass(PixelAccessor source, byte[] output, int width, int height)
+ protected override void SecondPass(ImageBase source, byte[] output, int width, int height)
{
// Load up the values for the first pixel. We can use these to speed up the second
// pass of the algorithm by avoiding transforming rows of identical color.
diff --git a/src/ImageSharp/Quantizers/Quantizer{TPixel}.cs b/src/ImageSharp/Quantizers/Quantizer{TPixel}.cs
index 48f33f98b..e99402996 100644
--- a/src/ImageSharp/Quantizers/Quantizer{TPixel}.cs
+++ b/src/ImageSharp/Quantizers/Quantizer{TPixel}.cs
@@ -54,35 +54,30 @@ namespace ImageSharp.Quantizers
int height = image.Height;
int width = image.Width;
byte[] quantizedPixels = new byte[width * height];
- TPixel[] colorPalette;
- using (PixelAccessor pixels = image.Lock())
+ // Call the FirstPass function if not a single pass algorithm.
+ // For something like an Octree quantizer, this will run through
+ // all image pixels, build a data structure, and create a palette.
+ if (!this.singlePass)
{
- // Call the FirstPass function if not a single pass algorithm.
- // For something like an Octree quantizer, this will run through
- // all image pixels, build a data structure, and create a palette.
- if (!this.singlePass)
- {
- this.FirstPass(pixels, width, height);
- }
+ this.FirstPass(image, width, height);
+ }
- // Collect the palette. Required before the second pass runs.
- colorPalette = this.GetPalette();
+ // Collect the palette. Required before the second pass runs.
+ TPixel[] colorPalette = this.GetPalette();
- if (this.Dither)
- {
- // We clone the image as we don't want to alter the original.
- using (Image clone = new Image(image))
- using (PixelAccessor clonedPixels = clone.Lock())
- {
- this.SecondPass(clonedPixels, quantizedPixels, width, height);
- }
- }
- else
+ if (this.Dither)
+ {
+ // We clone the image as we don't want to alter the original.
+ using (var clone = new Image(image))
{
- this.SecondPass(pixels, quantizedPixels, width, height);
+ this.SecondPass(clone, quantizedPixels, width, height);
}
}
+ else
+ {
+ this.SecondPass(image, quantizedPixels, width, height);
+ }
return new QuantizedImage(width, height, colorPalette, quantizedPixels);
}
@@ -93,7 +88,7 @@ namespace ImageSharp.Quantizers
/// The source data
/// The width in pixels of the image.
/// The height in pixels of the image.
- protected virtual void FirstPass(PixelAccessor source, int width, int height)
+ protected virtual void FirstPass(ImageBase source, int width, int height)
{
// Loop through each row
for (int y = 0; y < height; y++)
@@ -114,7 +109,7 @@ namespace ImageSharp.Quantizers
/// The output pixel array
/// The width in pixels of the image
/// The height in pixels of the image
- protected abstract void SecondPass(PixelAccessor source, byte[] output, int width, int height);
+ protected abstract void SecondPass(ImageBase source, byte[] output, int width, int height);
///
/// Override this to process the pixel in the first pass of the algorithm
@@ -155,7 +150,7 @@ namespace ImageSharp.Quantizers
// Not found - loop through the palette and find the nearest match.
byte colorIndex = 0;
float leastDistance = int.MaxValue;
- Vector4 vector = pixel.ToVector4();
+ var vector = pixel.ToVector4();
for (int index = 0; index < colorPalette.Length; index++)
{
diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
index fb63c9dcd..8d98a29d8 100644
--- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
+++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
@@ -183,7 +183,7 @@ namespace ImageSharp.Quantizers
float b = Volume(this.colorCube[k], this.vmb) / weight;
float a = Volume(this.colorCube[k], this.vma) / weight;
- TPixel color = default(TPixel);
+ var color = default(TPixel);
color.PackFromVector4(new Vector4(r, g, b, a) / 255F);
this.palette[k] = color;
}
@@ -221,7 +221,7 @@ namespace ImageSharp.Quantizers
}
///
- protected override void FirstPass(PixelAccessor source, int width, int height)
+ protected override void FirstPass(ImageBase source, int width, int height)
{
// Build up the 3-D color histogram
// Loop through each row
@@ -240,7 +240,7 @@ namespace ImageSharp.Quantizers
}
///
- protected override void SecondPass(PixelAccessor source, byte[] output, int width, int height)
+ protected override void SecondPass(ImageBase source, byte[] output, int width, int height)
{
// Load up the values for the first pixel. We can use these to speed up the second
// pass of the algorithm by avoiding transforming rows of identical color.