From 717daed35e7badbd4f706f4fe8e8301ad0d6c8d9 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Fri, 19 May 2017 13:01:35 +0100 Subject: [PATCH 01/84] Load from pixel data methods --- src/ImageSharp/Image/Image.LoadPixelData.cs | 100 ++++++++++++++++++ .../PixelFormats/PixelOperations{TPixel}.cs | 22 ++++ .../ImageSharp.Tests/Image/ImageLoadTests.cs | 42 ++++++++ 3 files changed, 164 insertions(+) create mode 100644 src/ImageSharp/Image/Image.LoadPixelData.cs diff --git a/src/ImageSharp/Image/Image.LoadPixelData.cs b/src/ImageSharp/Image/Image.LoadPixelData.cs new file mode 100644 index 000000000..fd7979190 --- /dev/null +++ b/src/ImageSharp/Image/Image.LoadPixelData.cs @@ -0,0 +1,100 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.IO; + using System.Runtime.CompilerServices; + using System.Threading.Tasks; + using Formats; + using ImageSharp.Memory; + using ImageSharp.PixelFormats; + + /// + /// Adds static methods allowing the creation of new image from a byte array. + /// + public static partial class Image + { + /// + /// Create a new instance of the class from the given pixel data. + /// + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static Image LoadPixelData(TPixel[] data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(Configuration.Default, data, width, height); + + /// + /// Create a new instance of the class from the given pixel data. + /// + /// The config for the decoder. + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static Image LoadPixelData(Configuration config, TPixel[] data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(config, new Span(data), width, height); + + /// + /// Create a new instance of the class from the given byte array as raw pixel data. + /// + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static Image LoadPixelData(byte[] data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(Configuration.Default, data, width, height); + + /// + /// Create a new instance of the class from the given byte array as raw pixel data. + /// + /// The config for the decoder. + /// The byte array containing image data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static Image LoadPixelData(Configuration config, byte[] data, int width, int height) + where TPixel : struct, IPixel + { + int size = width * height; + using (var sourceBuffer = new Buffer(size)) + { + PixelOperations.Instance.PackFromRawBytes(new Span(data), sourceBuffer.Span, size); + return LoadPixelData(config, sourceBuffer.Span, width, height); + } + } + + /// + /// Create a new instance of the class from the given byte array as raw pixel data. + /// + /// The config for the decoder. + /// The Span containing the image Pixel data. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + private static Image LoadPixelData(Configuration config, Span data, int width, int height) + where TPixel : struct, IPixel + { + int count = width * height; + Guard.MustBeGreaterThanOrEqualTo(data.Length, width * height, nameof(data)); + var image = new Image(config, width, height); + var dest = new Span(image.Pixels, 0, count); + + SpanHelper.Copy(data, dest, count); + + return image; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 993a11232..b29af94ee 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -249,5 +249,27 @@ namespace ImageSharp.PixelFormats sp.ToZyxwBytes(destBytes, i * 4); } } + + /// + /// Bulk conversion of data from series bytes to a series of Pixels. + /// + /// The to the source bytes. + /// The to the destination colors. + /// The number of pixels to convert. + internal virtual void PackFromRawBytes(Span sourceBytes, Span destColors, int count) + { + Guard.MustBeSizedAtLeast(sourceBytes, count * Unsafe.SizeOf(), nameof(sourceBytes)); + Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); + + ref TPixel sourceRef = ref Unsafe.As(ref sourceBytes.DangerousGetPinnableReference()); + ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); + + for (int i = 0; i < count; i++) + { + ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); + ref TPixel dp = ref Unsafe.Add(ref destRef, i); + dp = sp; + } + } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs index 4cdf529e6..7a5b8ffc5 100644 --- a/tests/ImageSharp.Tests/Image/ImageLoadTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageLoadTests.cs @@ -526,6 +526,48 @@ namespace ImageSharp.Tests this.localDecoder.Verify(x => x.Decode(Configuration.Default, this.DataStream, this.decoderOptions)); } + [Fact] + public void LoadFromPixelData_Pixels() + { + var img = Image.LoadPixelData(new Rgba32[] { + Rgba32.Black, Rgba32.White, + Rgba32.White, Rgba32.Black, + }, 2, 2); + + Assert.NotNull(img); + using (var px = img.Lock()) + { + Assert.Equal(Rgba32.Black, px[0, 0]); + Assert.Equal(Rgba32.White, px[0, 1]); + + Assert.Equal(Rgba32.White, px[1, 0]); + Assert.Equal(Rgba32.Black, px[1, 1]); + + } + } + + [Fact] + public void LoadFromPixelData_Bytes() + { + var img = Image.LoadPixelData(new byte[] { + 0,0,0,255, // 0,0 + 255,255,255,255, // 0,1 + 255,255,255,255, // 1,0 + 0,0,0,255, // 1,1 + }, 2, 2); + + Assert.NotNull(img); + using (var px = img.Lock()) + { + Assert.Equal(Rgba32.Black, px[0, 0]); + Assert.Equal(Rgba32.White, px[0, 1]); + + Assert.Equal(Rgba32.White, px[1, 0]); + Assert.Equal(Rgba32.Black, px[1, 1]); + + } + } + public void Dispose() { // clean up the global object; From cad87f6cddedcf437214b89bc26f4d4f33559cfb Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Fri, 19 May 2017 13:56:13 +0100 Subject: [PATCH 02/84] updated to make better use of Span --- src/ImageSharp/Image/Image.LoadPixelData.cs | 40 +++++-------------- .../PixelFormats/PixelOperations{TPixel}.cs | 22 ---------- 2 files changed, 10 insertions(+), 52 deletions(-) diff --git a/src/ImageSharp/Image/Image.LoadPixelData.cs b/src/ImageSharp/Image/Image.LoadPixelData.cs index fd7979190..75aa318be 100644 --- a/src/ImageSharp/Image/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image/Image.LoadPixelData.cs @@ -14,49 +14,36 @@ namespace ImageSharp using ImageSharp.PixelFormats; /// - /// Adds static methods allowing the creation of new image from a byte array. + /// Adds static methods allowing the creation of new image from raw pixel data. /// public static partial class Image { /// - /// Create a new instance of the class from the given pixel data. + /// Create a new instance of the class from the raw data. /// /// The byte array containing image data. /// The width of the final image. /// The height of the final image. /// The pixel format. /// A new . - public static Image LoadPixelData(TPixel[] data, int width, int height) + public static Image LoadPixelData(Span data, int width, int height) where TPixel : struct, IPixel => LoadPixelData(Configuration.Default, data, width, height); /// - /// Create a new instance of the class from the given pixel data. - /// - /// The config for the decoder. - /// The byte array containing image data. - /// The width of the final image. - /// The height of the final image. - /// The pixel format. - /// A new . - public static Image LoadPixelData(Configuration config, TPixel[] data, int width, int height) - where TPixel : struct, IPixel - => LoadPixelData(config, new Span(data), width, height); - - /// - /// Create a new instance of the class from the given byte array as raw pixel data. + /// Create a new instance of the class from the given byte array in format. /// /// The byte array containing image data. /// The width of the final image. /// The height of the final image. /// The pixel format. /// A new . - public static Image LoadPixelData(byte[] data, int width, int height) + public static Image LoadPixelData(Span data, int width, int height) where TPixel : struct, IPixel => LoadPixelData(Configuration.Default, data, width, height); /// - /// Create a new instance of the class from the given byte array as raw pixel data. + /// Create a new instance of the class from the given byte array in format. /// /// The config for the decoder. /// The byte array containing image data. @@ -64,19 +51,12 @@ namespace ImageSharp /// The height of the final image. /// The pixel format. /// A new . - public static Image LoadPixelData(Configuration config, byte[] data, int width, int height) + public static Image LoadPixelData(Configuration config, Span data, int width, int height) where TPixel : struct, IPixel - { - int size = width * height; - using (var sourceBuffer = new Buffer(size)) - { - PixelOperations.Instance.PackFromRawBytes(new Span(data), sourceBuffer.Span, size); - return LoadPixelData(config, sourceBuffer.Span, width, height); - } - } + => LoadPixelData(config, data.NonPortableCast(), width, height); /// - /// Create a new instance of the class from the given byte array as raw pixel data. + /// Create a new instance of the class from the raw data. /// /// The config for the decoder. /// The Span containing the image Pixel data. @@ -84,7 +64,7 @@ namespace ImageSharp /// The height of the final image. /// The pixel format. /// A new . - private static Image LoadPixelData(Configuration config, Span data, int width, int height) + public static Image LoadPixelData(Configuration config, Span data, int width, int height) where TPixel : struct, IPixel { int count = width * height; diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index b29af94ee..993a11232 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -249,27 +249,5 @@ namespace ImageSharp.PixelFormats sp.ToZyxwBytes(destBytes, i * 4); } } - - /// - /// Bulk conversion of data from series bytes to a series of Pixels. - /// - /// The to the source bytes. - /// The to the destination colors. - /// The number of pixels to convert. - internal virtual void PackFromRawBytes(Span sourceBytes, Span destColors, int count) - { - Guard.MustBeSizedAtLeast(sourceBytes, count * Unsafe.SizeOf(), nameof(sourceBytes)); - Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors)); - - ref TPixel sourceRef = ref Unsafe.As(ref sourceBytes.DangerousGetPinnableReference()); - ref TPixel destRef = ref destColors.DangerousGetPinnableReference(); - - for (int i = 0; i < count; i++) - { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp = sp; - } - } } } \ No newline at end of file From d8b5acf4f22eb8bf72842ff1acd2a0a3f3428335 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 23 May 2017 23:03:41 +1000 Subject: [PATCH 03/84] Fix png to gif transparency --- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 55 +++++--------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 5dc1a150d..ad0ecc88f 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -69,7 +69,7 @@ namespace ImageSharp.Formats this.Quantizer = this.options.Quantizer ?? new OctreeQuantizer(); // Do not use IDisposable pattern here as we want to preserve the stream. - EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream); + var writer = new EndianBinaryWriter(Endianness.LittleEndian, stream); // Ensure that quality can be set but has a fallback. int quality = this.options.Quality > 0 ? this.options.Quality : image.MetaData.Quality; @@ -82,7 +82,7 @@ namespace ImageSharp.Formats this.hasFrames = image.Frames.Any(); // Dithering when animating gifs is a bad idea as we introduce pixel tearing across frames. - IQuantizer ditheredQuantizer = (IQuantizer)this.Quantizer; + var ditheredQuantizer = (IQuantizer)this.Quantizer; ditheredQuantizer.Dither = !this.hasFrames; QuantizedImage quantized = ditheredQuantizer.Quantize(image, quality); @@ -96,7 +96,7 @@ namespace ImageSharp.Formats this.WriteLogicalScreenDescriptor(image, writer, index); // Write the first frame. - this.WriteGraphicalControlExtension(image, writer, index); + this.WriteGraphicalControlExtension(image.MetaData, writer, index); this.WriteComments(image, writer); this.WriteImageDescriptor(image, writer); this.WriteColorTable(quantized, writer); @@ -113,7 +113,7 @@ namespace ImageSharp.Formats ImageFrame frame = image.Frames[i]; QuantizedImage quantizedFrame = ditheredQuantizer.Quantize(frame, quality); - this.WriteGraphicalControlExtension(frame, writer, this.GetTransparentIndex(quantizedFrame)); + this.WriteGraphicalControlExtension(frame.MetaData, writer, this.GetTransparentIndex(quantizedFrame)); this.WriteImageDescriptor(frame, writer); this.WriteColorTable(quantizedFrame, writer); this.WriteImageData(quantizedFrame, writer); @@ -187,7 +187,7 @@ namespace ImageSharp.Formats private void WriteLogicalScreenDescriptor(Image image, EndianBinaryWriter writer, int tranparencyIndex) where TPixel : struct, IPixel { - GifLogicalScreenDescriptor descriptor = new GifLogicalScreenDescriptor + var descriptor = new GifLogicalScreenDescriptor { Width = (short)image.Width, Height = (short)image.Height, @@ -199,7 +199,7 @@ namespace ImageSharp.Formats writer.Write((ushort)descriptor.Width); writer.Write((ushort)descriptor.Height); - PackedField field = default(PackedField); + var field = default(PackedField); field.SetBit(0, descriptor.GlobalColorTableFlag); // 1 : Global color table flag = 1 || 0 (GCT used/ not used) field.SetBits(1, 3, descriptor.GlobalColorTableSize); // 2-4 : color resolution field.SetBit(4, false); // 5 : GCT sort flag = 0 @@ -251,7 +251,7 @@ namespace ImageSharp.Formats private void WriteComments(Image image, EndianBinaryWriter writer) where TPixel : struct, IPixel { - if (this.options.IgnoreMetadata == true) + if (this.options.IgnoreMetadata) { return; } @@ -278,44 +278,15 @@ namespace ImageSharp.Formats /// /// Writes the graphics control extension to the stream. /// - /// The pixel format. - /// The to encode. - /// The stream to write to. - /// The index of the color in the color palette to make transparent. - private void WriteGraphicalControlExtension(Image image, EndianBinaryWriter writer, int transparencyIndex) - where TPixel : struct, IPixel - { - this.WriteGraphicalControlExtension(image, image.MetaData, writer, transparencyIndex); - } - - /// - /// Writes the graphics control extension to the stream. - /// - /// The pixel format. - /// The to encode. - /// The stream to write to. - /// The index of the color in the color palette to make transparent. - private void WriteGraphicalControlExtension(ImageFrame imageFrame, EndianBinaryWriter writer, int transparencyIndex) - where TPixel : struct, IPixel - { - this.WriteGraphicalControlExtension(imageFrame, imageFrame.MetaData, writer, transparencyIndex); - } - - /// - /// Writes the graphics control extension to the stream. - /// - /// The pixel format. - /// The to encode. /// The metadata of the image or frame. /// The stream to write to. /// The index of the color in the color palette to make transparent. - private void WriteGraphicalControlExtension(ImageBase image, IMetaData metaData, EndianBinaryWriter writer, int transparencyIndex) - where TPixel : struct, IPixel + private void WriteGraphicalControlExtension(IMetaData metaData, EndianBinaryWriter writer, int transparencyIndex) { - GifGraphicsControlExtension extension = new GifGraphicsControlExtension() + var extension = new GifGraphicsControlExtension { DisposalMethod = metaData.DisposalMethod, - TransparencyFlag = transparencyIndex < 255, + TransparencyFlag = true, // TODO: The spec here is unclear. Can we get away with this? TransparencyIndex = transparencyIndex, DelayTime = metaData.FrameDelay }; @@ -326,7 +297,7 @@ namespace ImageSharp.Formats this.buffer[2] = 4; writer.Write(this.buffer, 0, 3); - PackedField field = default(PackedField); + var field = default(PackedField); field.SetBits(3, 3, (int)extension.DisposalMethod); // 1-3 : Reserved, 4-6 : Disposal // TODO: Allow this as an option. @@ -356,7 +327,7 @@ namespace ImageSharp.Formats writer.Write((ushort)image.Width); writer.Write((ushort)image.Height); - PackedField field = default(PackedField); + var field = default(PackedField); field.SetBit(0, true); // 1: Local color table flag = 1 (LCT used) field.SetBit(1, false); // 2: Interlace flag 0 field.SetBit(2, false); // 3: Sort flag 0 @@ -409,7 +380,7 @@ namespace ImageSharp.Formats private void WriteImageData(QuantizedImage image, EndianBinaryWriter writer) where TPixel : struct, IPixel { - using (LzwEncoder encoder = new LzwEncoder(image.Pixels, (byte)this.bitDepth)) + using (var encoder = new LzwEncoder(image.Pixels, (byte)this.bitDepth)) { encoder.Encode(writer.BaseStream); } From e768b091988dfb5bd5212fea679e0949312dd201 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 10:23:10 +1000 Subject: [PATCH 04/84] Internalize PixelAccessor --- src/ImageSharp.Drawing/Brushes/IBrush.cs | 4 +- .../Brushes/ImageBrush{TPixel}.cs | 37 +++--- .../Brushes/PatternBrush{TPixel}.cs | 18 +-- .../Brushes/Processors/BrushApplicator.cs | 9 +- .../Brushes/RecolorBrush{TPixel}.cs | 22 ++-- .../Brushes/SolidBrush{TPixel}.cs | 14 +-- src/ImageSharp.Drawing/Pens/IPen.cs | 4 +- src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs | 18 +-- .../Processors/DrawPathProcessor.cs | 9 +- .../Processors/FillProcessor.cs | 7 +- .../Processors/FillRegionProcessor.cs | 7 +- .../Dithering/ErrorDiffusion/ErrorDiffuser.cs | 14 +-- .../ErrorDiffusion/IErrorDiffuser.cs | 8 +- .../Dithering/Ordered/IOrderedDither.cs | 4 +- .../Dithering/Ordered/OrderedDither4x4.cs | 6 +- src/ImageSharp/Image/IImageBase{TPixel}.cs | 9 -- src/ImageSharp/Image/ImageBase{TPixel}.cs | 118 +++++++++++++++++- src/ImageSharp/Image/PixelAccessor{TPixel}.cs | 4 +- src/ImageSharp/Memory/Buffer2DExtensions.cs | 2 +- .../ErrorDiffusionDitherProcessor.cs | 17 ++- .../Binarization/OrderedDitherProcessor.cs | 21 ++-- .../Quantizers/OctreeQuantizer{TPixel}.cs | 4 +- .../Quantizers/PaletteQuantizer{TPixel}.cs | 4 +- .../Quantizers/Quantizer{TPixel}.cs | 45 +++---- .../Quantizers/WuQuantizer{TPixel}.cs | 6 +- 25 files changed, 248 insertions(+), 163 deletions(-) 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. From 0ea63d606fbdc19828dd6a4c1c290e6132e8fa5a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 10:46:30 +1000 Subject: [PATCH 05/84] Fix image disposal --- src/ImageSharp/Image/ImageBase{TPixel}.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ImageSharp/Image/ImageBase{TPixel}.cs b/src/ImageSharp/Image/ImageBase{TPixel}.cs index f7b294cf0..eb464c74e 100644 --- a/src/ImageSharp/Image/ImageBase{TPixel}.cs +++ b/src/ImageSharp/Image/ImageBase{TPixel}.cs @@ -309,7 +309,6 @@ namespace ImageSharp { PixelDataPool.Return(this.pixelBuffer); this.pixelBuffer = null; - this.span = null; } /// From a4ed3fe1887ad0455653e87f8f7b89dce12c1000 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 10:46:54 +1000 Subject: [PATCH 06/84] Updat exunit so so testrunner works --- tests/ImageSharp.Tests/ImageSharp.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index 55b3c80e3..fbfacee32 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -13,7 +13,7 @@ - + From 1aa94295efe1c8a5b842c4e9c8ea2436e4663da9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 11:51:35 +1000 Subject: [PATCH 07/84] Optimize some low hanging fruit --- .../Dithering/ErrorDiffusion/ErrorDiffuser.cs | 40 ++++++++++--------- .../ErrorDiffusionDitherProcessor.cs | 4 +- .../Quantizers/OctreeQuantizer{TPixel}.cs | 4 +- .../Quantizers/PaletteQuantizer{TPixel}.cs | 4 +- .../Quantizers/Quantizer{TPixel}.cs | 5 ++- .../Quantizers/WuQuantizer{TPixel}.cs | 4 +- 6 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs b/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs index 0c4192a87..408e6c383 100644 --- a/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs +++ b/src/ImageSharp/Dithering/ErrorDiffusion/ErrorDiffuser.cs @@ -5,6 +5,7 @@ namespace ImageSharp.Dithering { + using System; using System.Numerics; using System.Runtime.CompilerServices; @@ -95,30 +96,33 @@ namespace ImageSharp.Dithering for (int row = 0; row < this.matrixHeight; row++) { int matrixY = y + row; - - for (int col = 0; col < this.matrixWidth; col++) + if (matrixY > 0 && matrixY < height) { - int matrixX = x + (col - this.startingOffset); + Span rowSpan = image.GetRowSpan(matrixY); - if (matrixX > 0 && matrixX < width && matrixY > 0 && matrixY < height) + for (int col = 0; col < this.matrixWidth; col++) { - float coefficient = this.matrix[row, col]; + int matrixX = x + (col - this.startingOffset); - // Good to disable here as we are not comparing mathematical output. - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (coefficient == 0) + if (matrixX > 0 && matrixX < width) { - continue; + float coefficient = this.matrix[row, col]; + + // Good to disable here as we are not comparing mathematical output. + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (coefficient == 0) + { + continue; + } + + ref TPixel pixel = ref rowSpan[matrixX]; + var offsetColor = pixel.ToVector4(); + var coefficientVector = new Vector4(coefficient); + + Vector4 result = ((error * coefficientVector) / this.divisorVector) + offsetColor; + result.W = offsetColor.W; + pixel.PackFromVector4(result); } - - var coefficientVector = new Vector4(coefficient); - var offsetColor = image[matrixX, matrixY].ToVector4(); - Vector4 result = ((error * coefficientVector) / this.divisorVector) + offsetColor; - result.W = offsetColor.W; - - var packed = default(TPixel); - packed.PackFromVector4(result); - image[matrixX, matrixY] = packed; } } } diff --git a/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs index cb6f2fce4..47811f0ec 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs @@ -88,10 +88,12 @@ namespace ImageSharp.Processing.Processors for (int y = minY; y < maxY; y++) { int offsetY = y - startY; + Span row = source.GetRowSpan(offsetY); + for (int x = minX; x < maxX; x++) { int offsetX = x - startX; - TPixel sourceColor = source[offsetX, offsetY]; + TPixel sourceColor = row[offsetX]; 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/Quantizers/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs index f41272900..bd963c452 100644 --- a/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs @@ -78,11 +78,13 @@ namespace ImageSharp.Quantizers for (int y = 0; y < height; y++) { + Span row = source.GetRowSpan(y); + // And loop through each column for (int x = 0; x < width; x++) { // Get the pixel. - sourcePixel = source[x, y]; + sourcePixel = row[x]; // Check if this is the same as the last pixel. If so use that value // rather than calculating it again. This is an inexpensive optimization. diff --git a/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs index 52d3f320d..cf3ff94ee 100644 --- a/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs @@ -84,11 +84,13 @@ namespace ImageSharp.Quantizers for (int y = 0; y < height; y++) { + Span row = source.GetRowSpan(y); + // And loop through each column for (int x = 0; x < width; x++) { // Get the pixel. - sourcePixel = source[x, y]; + sourcePixel = row[x]; // Check if this is the same as the last pixel. If so use that value // rather than calculating it again. This is an inexpensive optimization. diff --git a/src/ImageSharp/Quantizers/Quantizer{TPixel}.cs b/src/ImageSharp/Quantizers/Quantizer{TPixel}.cs index e99402996..2e3ea7a54 100644 --- a/src/ImageSharp/Quantizers/Quantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/Quantizer{TPixel}.cs @@ -5,6 +5,7 @@ namespace ImageSharp.Quantizers { + using System; using System.Collections.Generic; using System.Numerics; using System.Runtime.CompilerServices; @@ -93,11 +94,13 @@ namespace ImageSharp.Quantizers // Loop through each row for (int y = 0; y < height; y++) { + Span row = source.GetRowSpan(y); + // And loop through each column for (int x = 0; x < width; x++) { // Now I have the pixel, call the FirstPassQuantize function... - this.InitialQuantizePixel(source[x, y]); + this.InitialQuantizePixel(row[x]); } } } diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs index 8d98a29d8..aecca771c 100644 --- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs @@ -252,11 +252,13 @@ namespace ImageSharp.Quantizers for (int y = 0; y < height; y++) { + Span row = source.GetRowSpan(y); + // And loop through each column for (int x = 0; x < width; x++) { // Get the pixel. - sourcePixel = source[x, y]; + sourcePixel = row[x]; // Check if this is the same as the last pixel. If so use that value // rather than calculating it again. This is an inexpensive optimization. From e508d7e419c8c334a86d92fa1fc92c015bfd5f7f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 12:37:44 +1000 Subject: [PATCH 08/84] Add benchmark, update readme --- README.md | 13 ++- .../ImageSharp.Benchmarks/Image/CopyPixels.cs | 87 +++++++++++++++++-- 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ca2427546..0f902fc17 100644 --- a/README.md +++ b/README.md @@ -106,17 +106,22 @@ using (Image image = Image.Load(stream)) } ``` -Setting individual pixel values is perfomed as follows: +Setting individual pixel values can perfomed as follows: ```csharp +// Individual pixels using (Image image = new Image(400, 400) -using (PixelAccessor pixels = image.Lock()) { - pixels[200, 200] = Rgba32.White; + image[200, 200] = Rgba32.White; } ``` -For advanced usage there are multiple [PixelFormat implementations](https://github.com/JimBobSquarePants/ImageSharp/tree/master/src/ImageSharp/PixelFormats) available allowing developers to implement their own color models in the same manner as Microsoft XNA Game Studio and MonoGame. +For optimized access within a loop it is recommended that the following methods are used. + +1. `image.GetRowSpan(y)` +2. `image.GetRowSPan(x, y)` + +For advanced pixel format usage there are multiple [PixelFormat implementations](https://github.com/JimBobSquarePants/ImageSharp/tree/master/src/ImageSharp/PixelFormats) available allowing developers to implement their own color models in the same manner as Microsoft XNA Game Studio and MonoGame. All in all this should allow image processing to be much more accessible to developers which has always been my goal from the start. diff --git a/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs b/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs index 5b5d14750..1d4ed1193 100644 --- a/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs +++ b/tests/ImageSharp.Benchmarks/Image/CopyPixels.cs @@ -5,19 +5,20 @@ namespace ImageSharp.Benchmarks.Image { + using System; using System.Threading.Tasks; using BenchmarkDotNet.Attributes; - using ImageSharp.PixelFormats; + using ImageSharp.Memory; public class CopyPixels : BenchmarkBase { - [Benchmark(Description = "Copy by Pixel")] - public Rgba32 CopyByPixel() + [Benchmark(Baseline = true, Description = "PixelAccessor Copy by indexer")] + public Rgba32 CopyByPixelAccesor() { - using (Image source = new Image(1024, 768)) - using (Image target = new Image(1024, 768)) + using (var source = new Image(1024, 768)) + using (var target = new Image(1024, 768)) { using (PixelAccessor sourcePixels = source.Lock()) using (PixelAccessor targetPixels = target.Lock()) @@ -38,5 +39,81 @@ namespace ImageSharp.Benchmarks.Image } } } + + [Benchmark(Description = "PixelAccessor Copy by Span")] + public Rgba32 CopyByPixelAccesorSpan() + { + using (var source = new Image(1024, 768)) + using (var target = new Image(1024, 768)) + { + using (PixelAccessor sourcePixels = source.Lock()) + using (PixelAccessor targetPixels = target.Lock()) + { + Parallel.For( + 0, + source.Height, + Configuration.Default.ParallelOptions, + y => + { + Span sourceRow = sourcePixels.GetRowSpan(y); + Span targetRow = targetPixels.GetRowSpan(y); + + for (int x = 0; x < source.Width; x++) + { + targetRow[x] = sourceRow[x]; + } + }); + + return targetPixels[0, 0]; + } + } + } + + [Benchmark(Description = "Copy by indexer")] + public Rgba32 Copy() + { + using (var source = new Image(1024, 768)) + using (var target = new Image(1024, 768)) + { + Parallel.For( + 0, + source.Height, + Configuration.Default.ParallelOptions, + y => + { + for (int x = 0; x < source.Width; x++) + { + target[x, y] = source[x, y]; + } + }); + + return target[0, 0]; + } + } + + [Benchmark(Description = "Copy by Span")] + public Rgba32 CopySpan() + { + using (var source = new Image(1024, 768)) + using (var target = new Image(1024, 768)) + { + Parallel.For( + 0, + source.Height, + Configuration.Default.ParallelOptions, + y => + { + Span sourceRow = source.GetRowSpan(y); + Span targetRow = target.GetRowSpan(y); + + for (int x = 0; x < source.Width; x++) + { + targetRow[x] = sourceRow[x]; + } + }); + + return target[0, 0]; + } + } } } From 49a95e4ba042a8cfebb300f3bbd860a7c02c4669 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 12:58:40 +1000 Subject: [PATCH 09/84] Optimize dither --- README.md | 2 +- .../Binarization/BinaryThresholdProcessor.cs | 33 +++++++++---------- .../Binarization/OrderedDitherProcessor.cs | 3 +- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 0f902fc17..c672d7ca3 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ using (Image image = new Image(400, 400) For optimized access within a loop it is recommended that the following methods are used. 1. `image.GetRowSpan(y)` -2. `image.GetRowSPan(x, y)` +2. `image.GetRowSpan(x, y)` For advanced pixel format usage there are multiple [PixelFormat implementations](https://github.com/JimBobSquarePants/ImageSharp/tree/master/src/ImageSharp/PixelFormats) available allowing developers to implement their own color models in the same manner as Microsoft XNA Game Studio and MonoGame. diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs index 5cd67f053..a2fa1ddf3 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs @@ -83,25 +83,22 @@ namespace ImageSharp.Processing.Processors startY = 0; } - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + Span row = source.GetRowSpan(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 color = sourcePixels[offsetX, offsetY]; - - // Any channel will do since it's Grayscale. - sourcePixels[offsetX, offsetY] = color.ToVector4().X >= threshold ? upper : lower; - } - }); - } + ref TPixel color = ref row[x - startX]; + + // Any channel will do since it's Grayscale. + color = color.ToVector4().X >= threshold ? upper : lower; + } + }); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs index 1bdb4d53b..898389777 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs @@ -97,11 +97,12 @@ namespace ImageSharp.Processing.Processors for (int y = minY; y < maxY; y++) { int offsetY = y - startY; + Span row = source.GetRowSpan(offsetY); for (int x = minX; x < maxX; x++) { int offsetX = x - startX; - TPixel sourceColor = source[offsetX, offsetY]; + TPixel sourceColor = row[offsetX]; this.Dither.Dither(source, sourceColor, this.UpperColor, this.LowerColor, bytes, this.Index, offsetX, offsetY, maxX, maxY); } } From 5a884da4c0a24e854a90d52fe0fc25c2c40f6cec Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 13:07:54 +1000 Subject: [PATCH 10/84] Optimize ColorMatrixProcessors --- .../ColorMatrix/ColorMatrixProcessor.cs | 41 ++++++------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/ColorMatrix/ColorMatrixProcessor.cs b/src/ImageSharp/Processing/Processors/ColorMatrix/ColorMatrixProcessor.cs index cfe50150f..49af2667d 100644 --- a/src/ImageSharp/Processing/Processors/ColorMatrix/ColorMatrixProcessor.cs +++ b/src/ImageSharp/Processing/Processors/ColorMatrix/ColorMatrixProcessor.cs @@ -7,7 +7,6 @@ namespace ImageSharp.Processing.Processors { using System; using System.Numerics; - using System.Runtime.CompilerServices; using System.Threading.Tasks; using ImageSharp.PixelFormats; @@ -61,39 +60,23 @@ namespace ImageSharp.Processing.Processors this.ParallelOptions, y => { - int offsetY = y - startY; + Span row = source.GetRowSpan(y - startY); + for (int x = minX; x < maxX; x++) { - int offsetX = x - startX; - sourcePixels[offsetX, offsetY] = this.ApplyMatrix(sourcePixels[offsetX, offsetY], matrix, compand); - } - }); - } - } + ref TPixel pixel = ref row[x - startX]; + var vector = pixel.ToVector4(); - /// - /// Applies the color matrix against the given color. - /// - /// The source color. - /// The matrix. - /// Whether to compand the color during processing. - /// - /// The . - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private TPixel ApplyMatrix(TPixel color, Matrix4x4 matrix, bool compand) - { - Vector4 vector = color.ToVector4(); + if (compand) + { + vector = vector.Expand(); + } - if (compand) - { - vector = vector.Expand(); + vector = Vector4.Transform(vector, matrix); + pixel.PackFromVector4(compand ? vector.Compress() : vector); + } + }); } - - vector = Vector4.Transform(vector, matrix); - TPixel packed = default(TPixel); - packed.PackFromVector4(compand ? vector.Compress() : vector); - return packed; } } } \ No newline at end of file From 2ed67f0562c5ecae231e22fdaeda2776473001d2 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 13:43:28 +1000 Subject: [PATCH 11/84] Optimize Convolution processors --- src/ImageSharp/Image/ImageBase{TPixel}.cs | 9 +++++++ src/ImageSharp/Image/PixelAccessor{TPixel}.cs | 26 ++++++++++--------- src/ImageSharp/Memory/SpanHelper.cs | 2 +- .../Convolution/Convolution2DProcessor.cs | 18 +++++++------ .../Convolution/Convolution2PassProcessor.cs | 14 +++++----- .../Convolution/ConvolutionProcessor.cs | 16 +++++++----- 6 files changed, 51 insertions(+), 34 deletions(-) diff --git a/src/ImageSharp/Image/ImageBase{TPixel}.cs b/src/ImageSharp/Image/ImageBase{TPixel}.cs index eb464c74e..60fcdda48 100644 --- a/src/ImageSharp/Image/ImageBase{TPixel}.cs +++ b/src/ImageSharp/Image/ImageBase{TPixel}.cs @@ -231,6 +231,15 @@ namespace ImageSharp return new PixelAccessor(this); } + /// + /// Copies the pixels to another of the same size. + /// + /// The target pixel buffer accessor. + internal void CopyTo(PixelAccessor target) + { + SpanHelper.Copy(this.span, target.PixelBuffer.Span); + } + /// /// Switches the buffers used by the image and the PixelAccessor meaning that the Image will "own" the buffer from the PixelAccessor and the PixelAccessor will now own the Images buffer. /// diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs index 240e65c82..1d776c258 100644 --- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs @@ -20,6 +20,13 @@ namespace ImageSharp internal sealed class PixelAccessor : IDisposable, IBuffer2D where TPixel : struct, IPixel { +#pragma warning disable SA1401 // Fields must be private + /// + /// The containing the pixel data. + /// + internal Buffer2D PixelBuffer; +#pragma warning restore SA1401 // Fields must be private + /// /// A value indicating whether this instance of the given entity has been disposed. /// @@ -31,11 +38,6 @@ namespace ImageSharp /// private bool isDisposed; - /// - /// The containing the pixel data. - /// - private Buffer2D pixelBuffer; - /// /// Initializes a new instance of the class. /// @@ -88,7 +90,7 @@ namespace ImageSharp /// /// Gets the pixel buffer array. /// - public TPixel[] PixelArray => this.pixelBuffer.Array; + public TPixel[] PixelArray => this.PixelBuffer.Array; /// /// Gets the size of a single pixel in the number of bytes. @@ -116,7 +118,7 @@ namespace ImageSharp public ParallelOptions ParallelOptions { get; } /// - Span IBuffer2D.Span => this.pixelBuffer; + Span IBuffer2D.Span => this.PixelBuffer; private static PixelOperations Operations => PixelOperations.Instance; @@ -156,7 +158,7 @@ namespace ImageSharp // Note disposing is done. this.isDisposed = true; - this.pixelBuffer.Dispose(); + this.PixelBuffer.Dispose(); // This object will be cleaned up by the Dispose method. // Therefore, you should call GC.SuppressFinalize to @@ -171,7 +173,7 @@ namespace ImageSharp /// public void Reset() { - this.pixelBuffer.Clear(); + this.PixelBuffer.Clear(); } /// @@ -243,7 +245,7 @@ namespace ImageSharp /// If is true then caller is responsible for ensuring is called. internal TPixel[] ReturnCurrentColorsAndReplaceThemInternally(int width, int height, TPixel[] pixels) { - TPixel[] oldPixels = this.pixelBuffer.TakeArrayOwnership(); + TPixel[] oldPixels = this.PixelBuffer.TakeArrayOwnership(); this.SetPixelBufferUnsafe(width, height, pixels); return oldPixels; } @@ -254,7 +256,7 @@ namespace ImageSharp /// The target pixel buffer accessor. internal void CopyTo(PixelAccessor target) { - SpanHelper.Copy(this.pixelBuffer.Span, target.pixelBuffer.Span); + SpanHelper.Copy(this.PixelBuffer.Span, target.PixelBuffer.Span); } /// @@ -425,7 +427,7 @@ namespace ImageSharp /// The pixel buffer private void SetPixelBufferUnsafe(int width, int height, Buffer2D pixels) { - this.pixelBuffer = pixels; + this.PixelBuffer = pixels; this.Width = width; this.Height = height; diff --git a/src/ImageSharp/Memory/SpanHelper.cs b/src/ImageSharp/Memory/SpanHelper.cs index 57b771591..0e794e1b5 100644 --- a/src/ImageSharp/Memory/SpanHelper.cs +++ b/src/ImageSharp/Memory/SpanHelper.cs @@ -70,7 +70,7 @@ namespace ImageSharp.Memory public static void Copy(Span source, Span destination) where T : struct { - Copy(source, destination, source.Length); + Copy(source, destination, Math.Min(source.Length, destination.Length)); } /// diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs index 29086b53f..b6b56adb3 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs @@ -5,6 +5,7 @@ namespace ImageSharp.Processing.Processors { + using System; using System.Numerics; using System.Threading.Tasks; @@ -56,10 +57,9 @@ namespace ImageSharp.Processing.Processors int maxY = endY - 1; int maxX = endX - 1; - using (PixelAccessor targetPixels = new PixelAccessor(source.Width, source.Height)) - using (PixelAccessor sourcePixels = source.Lock()) + using (var targetPixels = new PixelAccessor(source.Width, source.Height)) { - sourcePixels.CopyTo(targetPixels); + source.CopyTo(targetPixels); Parallel.For( startY, @@ -67,6 +67,9 @@ namespace ImageSharp.Processing.Processors this.ParallelOptions, y => { + Span sourceRow = source.GetRowSpan(y); + Span targetRow = targetPixels.GetRowSpan(y); + for (int x = startX; x < endX; x++) { float rX = 0; @@ -83,6 +86,7 @@ namespace ImageSharp.Processing.Processors int offsetY = y + fyr; offsetY = offsetY.Clamp(0, maxY); + Span sourceOffsetRow = source.GetRowSpan(offsetY); for (int fx = 0; fx < kernelXWidth; fx++) { @@ -90,8 +94,7 @@ namespace ImageSharp.Processing.Processors int offsetX = x + fxr; offsetX = offsetX.Clamp(0, maxX); - - Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4(); + var currentColor = sourceOffsetRow[offsetX].ToVector4(); if (fy < kernelXHeight) { @@ -115,9 +118,8 @@ namespace ImageSharp.Processing.Processors float green = MathF.Sqrt((gX * gX) + (gY * gY)); float blue = MathF.Sqrt((bX * bX) + (bY * bY)); - TPixel packed = default(TPixel); - packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W)); - targetPixels[x, y] = packed; + ref TPixel pixel = ref targetRow[x]; + pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W)); } }); diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs index e39104793..efc00b08f 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs @@ -46,7 +46,7 @@ namespace ImageSharp.Processing.Processors int width = source.Width; int height = source.Height; - using (PixelAccessor firstPassPixels = new PixelAccessor(width, height)) + using (var firstPassPixels = new PixelAccessor(width, height)) using (PixelAccessor sourcePixels = source.Lock()) { this.ApplyConvolution(firstPassPixels, sourcePixels, source.Bounds, this.KernelX); @@ -84,9 +84,11 @@ namespace ImageSharp.Processing.Processors this.ParallelOptions, y => { + Span targetRow = targetPixels.GetRowSpan(y); + for (int x = startX; x < endX; x++) { - Vector4 destination = default(Vector4); + var destination = default(Vector4); // Apply each matrix multiplier to the color components for each pixel. for (int fy = 0; fy < kernelHeight; fy++) @@ -95,6 +97,7 @@ namespace ImageSharp.Processing.Processors int offsetY = y + fyr; offsetY = offsetY.Clamp(0, maxY); + Span row = sourcePixels.GetRowSpan(offsetY); for (int fx = 0; fx < kernelWidth; fx++) { @@ -103,14 +106,13 @@ namespace ImageSharp.Processing.Processors offsetX = offsetX.Clamp(0, maxX); - Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4(); + var currentColor = row[offsetX].ToVector4(); destination += kernel[fy, fx] * currentColor; } } - TPixel packed = default(TPixel); - packed.PackFromVector4(destination); - targetPixels[x, y] = packed; + ref TPixel pixel = ref targetRow[x]; + pixel.PackFromVector4(destination); } }); } diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs index 17d5e3243..06607c87a 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs @@ -46,10 +46,9 @@ namespace ImageSharp.Processing.Processors int maxY = endY - 1; int maxX = endX - 1; - using (PixelAccessor targetPixels = new PixelAccessor(source.Width, source.Height)) - using (PixelAccessor sourcePixels = source.Lock()) + using (var targetPixels = new PixelAccessor(source.Width, source.Height)) { - sourcePixels.CopyTo(targetPixels); + source.CopyTo(targetPixels); Parallel.For( startY, @@ -57,6 +56,9 @@ namespace ImageSharp.Processing.Processors this.ParallelOptions, y => { + Span sourceRow = source.GetRowSpan(y); + Span targetRow = targetPixels.GetRowSpan(y); + for (int x = startX; x < endX; x++) { float red = 0; @@ -70,6 +72,7 @@ namespace ImageSharp.Processing.Processors int offsetY = y + fyr; offsetY = offsetY.Clamp(0, maxY); + Span sourceOffsetRow = source.GetRowSpan(offsetY); for (int fx = 0; fx < kernelLength; fx++) { @@ -78,7 +81,7 @@ namespace ImageSharp.Processing.Processors offsetX = offsetX.Clamp(0, maxX); - Vector4 currentColor = sourcePixels[offsetX, offsetY].ToVector4(); + var currentColor = sourceOffsetRow[offsetX].ToVector4(); currentColor *= this.KernelXY[fy, fx]; red += currentColor.X; @@ -87,9 +90,8 @@ namespace ImageSharp.Processing.Processors } } - TPixel packed = default(TPixel); - packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W)); - targetPixels[x, y] = packed; + ref TPixel pixel = ref targetRow[x]; + pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W)); } }); From 2423c680bbc6b05c2b2ddb7fc05232986d46040f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 13:58:10 +1000 Subject: [PATCH 12/84] Optimize Alpha --- .../Processors/Effects/AlphaProcessor.cs | 32 ++++++++----------- .../Processors/Filters/AlphaTest.cs | 4 +-- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Effects/AlphaProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/AlphaProcessor.cs index 5e7310e32..a3894f8d3 100644 --- a/src/ImageSharp/Processing/Processors/Effects/AlphaProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/AlphaProcessor.cs @@ -61,26 +61,22 @@ namespace ImageSharp.Processing.Processors startY = 0; } - Vector4 alphaVector = new Vector4(1, 1, 1, this.Value); + var alphaVector = new Vector4(1, 1, 1, this.Value); - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + Span row = source.GetRowSpan(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 packed = default(TPixel); - packed.PackFromVector4(sourcePixels[offsetX, offsetY].ToVector4() * alphaVector); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } + ref TPixel pixel = ref row[x - startX]; + pixel.PackFromVector4(pixel.ToVector4() * alphaVector); + } + }); } } } diff --git a/tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs b/tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs index e40e3a205..401ac916b 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs @@ -22,7 +22,7 @@ namespace ImageSharp.Tests [Theory] [MemberData(nameof(AlphaValues))] - public void ImageShouldApplyAlphaFilter(int value) + public void ImageShouldApplyAlphaFilter(float value) { string path = this.CreateOutputDirectory("Alpha"); @@ -39,7 +39,7 @@ namespace ImageSharp.Tests [Theory] [MemberData(nameof(AlphaValues))] - public void ImageShouldApplyAlphaFilterInBox(int value) + public void ImageShouldApplyAlphaFilterInBox(float value) { string path = this.CreateOutputDirectory("Alpha"); From 7c529d7ff8192b081db65d29258cfd863f9e76c5 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 14:04:47 +1000 Subject: [PATCH 13/84] Optimize BackgroundColor --- .../Processors/Effects/BackgroundColorProcessor.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs index cc95f15fc..153719191 100644 --- a/src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs @@ -6,7 +6,6 @@ namespace ImageSharp.Processing.Processors { using System; - using System.Numerics; using System.Threading.Tasks; using ImageSharp.Memory; @@ -64,9 +63,8 @@ namespace ImageSharp.Processing.Processors int width = maxX - minX; - using (Buffer colors = new Buffer(width)) - using (Buffer amount = new Buffer(width)) - using (PixelAccessor sourcePixels = source.Lock()) + using (var colors = new Buffer(width)) + using (var amount = new Buffer(width)) { for (int i = 0; i < width; i++) { @@ -81,11 +79,9 @@ namespace ImageSharp.Processing.Processors this.ParallelOptions, y => { - int offsetY = y - startY; + Span destination = source.GetRowSpan(y - startY).Slice(minX - startX, width); - Span destination = sourcePixels.GetRowSpan(offsetY).Slice(minX - startX, width); - - // this switched color & destination in the 2nd and 3rd places because we are applying the target colour under the current one + // This switched color & destination in the 2nd and 3rd places because we are applying the target colour under the current one blender.Blend(destination, colors, destination, amount); }); } From 334ba994e71756cb4f7bed839e7a21b5d4d94fcf Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 14:10:25 +1000 Subject: [PATCH 14/84] Optimize Brightness --- .../Processors/Effects/BrightnessProcessor.cs | 39 ++++++++----------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Effects/BrightnessProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/BrightnessProcessor.cs index f9f1585ea..121d25d1e 100644 --- a/src/ImageSharp/Processing/Processors/Effects/BrightnessProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/BrightnessProcessor.cs @@ -63,31 +63,26 @@ namespace ImageSharp.Processing.Processors startY = 0; } - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + Span row = source.GetRowSpan(y - startY); - // TODO: Check this with other formats. - Vector4 vector = sourcePixels[offsetX, offsetY].ToVector4().Expand(); - Vector3 transformed = new Vector3(vector.X, vector.Y, vector.Z) + new Vector3(brightness); - vector = new Vector4(transformed, vector.W); + for (int x = minX; x < maxX; x++) + { + ref TPixel pixel = ref row[x - startX]; - TPixel packed = default(TPixel); - packed.PackFromVector4(vector.Compress()); + // TODO: Check this with other formats. + Vector4 vector = pixel.ToVector4().Expand(); + Vector3 transformed = new Vector3(vector.X, vector.Y, vector.Z) + new Vector3(brightness); + vector = new Vector4(transformed, vector.W); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } + pixel.PackFromVector4(vector.Compress()); + } + }); } } } \ No newline at end of file From c5b332f965c3cc83e9e7819bb4cfe6d2de877a4b Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 14:15:57 +1000 Subject: [PATCH 15/84] Optimize Contrast --- .../Processors/Effects/ContrastProcessor.cs | 45 +++++++++---------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs index 8308c57e2..f5dc68545 100644 --- a/src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs @@ -45,8 +45,8 @@ namespace ImageSharp.Processing.Processors int endY = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; - Vector4 contrastVector = new Vector4(contrast, contrast, contrast, 1); - Vector4 shiftVector = new Vector4(.5F, .5F, .5F, 1); + var contrastVector = new Vector4(contrast, contrast, contrast, 1); + var shiftVector = new Vector4(.5F, .5F, .5F, 1); // Align start/end positions. int minX = Math.Max(0, startX); @@ -65,29 +65,28 @@ namespace ImageSharp.Processing.Processors startY = 0; } - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + int offsetY = y - startY; + Span row = source.GetRowSpan(y - startY); + + for (int x = minX; x < maxX; x++) { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; + int offsetX = x - startX; + ref TPixel pixel = ref row[x - startX]; - Vector4 vector = sourcePixels[offsetX, offsetY].ToVector4().Expand(); - vector -= shiftVector; - vector *= contrastVector; - vector += shiftVector; - TPixel packed = default(TPixel); - packed.PackFromVector4(vector.Compress()); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } + Vector4 vector = pixel.ToVector4().Expand(); + vector -= shiftVector; + vector *= contrastVector; + vector += shiftVector; + + pixel.PackFromVector4(vector.Compress()); + } + }); } } } \ No newline at end of file From a56a97a2e289cac0912110e2206c75689d36aad8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 14:21:11 +1000 Subject: [PATCH 16/84] Optimize Invert --- .../Processors/Effects/ContrastProcessor.cs | 2 -- .../Processors/Effects/InvertProcessor.cs | 35 +++++++++---------- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs index f5dc68545..1daead6e5 100644 --- a/src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs @@ -71,12 +71,10 @@ namespace ImageSharp.Processing.Processors this.ParallelOptions, y => { - int offsetY = y - startY; Span row = source.GetRowSpan(y - startY); for (int x = minX; x < maxX; x++) { - int offsetX = x - startX; ref TPixel pixel = ref row[x - startX]; Vector4 vector = pixel.ToVector4().Expand(); diff --git a/src/ImageSharp/Processing/Processors/Effects/InvertProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/InvertProcessor.cs index a0348970e..dc0b13442 100644 --- a/src/ImageSharp/Processing/Processors/Effects/InvertProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/InvertProcessor.cs @@ -44,27 +44,24 @@ namespace ImageSharp.Processing.Processors startY = 0; } - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + Span row = source.GetRowSpan(y - startY); + + for (int x = minX; x < maxX; x++) { - int offsetY = y - startY; - for (int x = minX; x < maxX; x++) - { - int offsetX = x - startX; - Vector4 color = sourcePixels[offsetX, offsetY].ToVector4(); - Vector3 vector = inverseVector - new Vector3(color.X, color.Y, color.Z); + ref TPixel pixel = ref row[x - startX]; - TPixel packed = default(TPixel); - packed.PackFromVector4(new Vector4(vector, color.W)); - sourcePixels[offsetX, offsetY] = packed; - } - }); - } + var vector = pixel.ToVector4(); + Vector3 vector3 = inverseVector - new Vector3(vector.X, vector.Y, vector.Z); + + pixel.PackFromVector4(new Vector4(vector3, vector.W)); + } + }); } } } \ No newline at end of file From 38f5340165260e6ce2f9d9c1f85518edaea9d243 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 14:41:34 +1000 Subject: [PATCH 17/84] Optimize OilPaint --- .../Effects/OilPaintingProcessor.cs | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs index 1f06924af..a43f77a1c 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs @@ -8,7 +8,7 @@ namespace ImageSharp.Processing.Processors using System; using System.Numerics; using System.Threading.Tasks; - + using ImageSharp.Memory; using ImageSharp.PixelFormats; /// @@ -69,10 +69,9 @@ namespace ImageSharp.Processing.Processors startX = 0; } - using (PixelAccessor targetPixels = new PixelAccessor(source.Width, source.Height)) - using (PixelAccessor sourcePixels = source.Lock()) + using (var targetPixels = new PixelAccessor(source.Width, source.Height)) { - sourcePixels.CopyTo(targetPixels); + source.CopyTo(targetPixels); Parallel.For( minY, @@ -80,6 +79,9 @@ namespace ImageSharp.Processing.Processors this.ParallelOptions, y => { + Span sourceRow = source.GetRowSpan(y); + Span targetRow = targetPixels.GetRowSpan(y); + for (int x = startX; x < endX; x++) { int maxIntensity = 0; @@ -107,6 +109,8 @@ namespace ImageSharp.Processing.Processors break; } + Span sourceOffsetRow = source.GetRowSpan(offsetY); + for (int fx = 0; fx <= radius; fx++) { int fxr = fx - radius; @@ -121,13 +125,13 @@ namespace ImageSharp.Processing.Processors if (offsetX < maxX) { // ReSharper disable once AccessToDisposedClosure - Vector4 color = sourcePixels[offsetX, offsetY].ToVector4(); + var vector = sourceOffsetRow[offsetX].ToVector4(); - float sourceRed = color.X; - float sourceBlue = color.Z; - float sourceGreen = color.Y; + float sourceRed = vector.X; + float sourceBlue = vector.Z; + float sourceGreen = vector.Y; - int currentIntensity = (int)Math.Round((sourceBlue + sourceGreen + sourceRed) / 3.0 * (levels - 1)); + int currentIntensity = (int)MathF.Round((sourceBlue + sourceGreen + sourceRed) / 3F * (levels - 1)); intensityBin[currentIntensity] += 1; blueBin[currentIntensity] += sourceBlue; @@ -146,9 +150,8 @@ namespace ImageSharp.Processing.Processors float green = MathF.Abs(greenBin[maxIndex] / maxIntensity); float blue = MathF.Abs(blueBin[maxIndex] / maxIntensity); - TPixel packed = default(TPixel); - packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W)); - targetPixels[x, y] = packed; + ref TPixel pixel = ref targetRow[x]; + pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W)); } } }); From 13738226accdea1475f310bc7587b747d14dd622 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 14:52:50 +1000 Subject: [PATCH 18/84] Optimize Pixellate --- .../Processors/Effects/PixelateProcessor.cs | 62 +++++++++---------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs index 0287eaab8..ba6bb5c9d 100644 --- a/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs @@ -66,47 +66,45 @@ namespace ImageSharp.Processing.Processors // Get the range on the y-plane to choose from. IEnumerable range = EnumerableExtensions.SteppedRange(minY, i => i < maxY, size); - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.ForEach( - range, - this.ParallelOptions, - y => + Parallel.ForEach( + range, + this.ParallelOptions, + y => + { + int offsetY = y - startY; + int offsetPy = offset; + + // Make sure that the offset is within the boundary of the image. + while (offsetY + offsetPy >= maxY) { - int offsetY = y - startY; - int offsetPy = offset; + offsetPy--; + } - for (int x = minX; x < maxX; x += size) - { - int offsetX = x - startX; - int offsetPx = offset; + Span row = source.GetRowSpan(offsetY + offsetPy); - // Make sure that the offset is within the boundary of the image. - while (offsetY + offsetPy >= maxY) - { - offsetPy--; - } + for (int x = minX; x < maxX; x += size) + { + int offsetX = x - startX; + int offsetPx = offset; - while (x + offsetPx >= maxX) - { - offsetPx--; - } + while (x + offsetPx >= maxX) + { + offsetPx--; + } - // Get the pixel color in the centre of the soon to be pixelated area. - // ReSharper disable AccessToDisposedClosure - TPixel pixel = sourcePixels[offsetX + offsetPx, offsetY + offsetPy]; + // Get the pixel color in the centre of the soon to be pixelated area. + TPixel pixel = row[offsetX + offsetPx]; - // For each pixel in the pixelate size, set it to the centre color. - for (int l = offsetY; l < offsetY + size && l < maxY; l++) + // For each pixel in the pixelate size, set it to the centre color. + for (int l = offsetY; l < offsetY + size && l < maxY; l++) + { + for (int k = offsetX; k < offsetX + size && k < maxX; k++) { - for (int k = offsetX; k < offsetX + size && k < maxX; k++) - { - sourcePixels[k, l] = pixel; - } + source[k, l] = pixel; } } - }); - } + } + }); } } } \ No newline at end of file From 5ad15fe31bafdd7a1a426a28d0fd64cc75b81703 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 15:00:04 +1000 Subject: [PATCH 19/84] Optimize Glow/Vignette --- .../Processors/Overlays/GlowProcessor.cs | 41 +++++++++---------- .../Processors/Overlays/VignetteProcessor.cs | 9 ++-- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs index 9de91c47b..23fea94e9 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs @@ -52,7 +52,7 @@ namespace ImageSharp.Processing.Processors int startX = sourceRectangle.X; int endX = sourceRectangle.Right; TPixel glowColor = this.GlowColor; - Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2(); + var centre = Rectangle.Center(sourceRectangle).ToVector2(); float maxDistance = this.Radius > 0 ? MathF.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; // Align start/end positions. @@ -73,8 +73,7 @@ namespace ImageSharp.Processing.Processors } int width = maxX - minX; - using (Buffer rowColors = new Buffer(width)) - using (PixelAccessor sourcePixels = source.Lock()) + using (var rowColors = new Buffer(width)) { for (int i = 0; i < width; i++) { @@ -82,26 +81,26 @@ namespace ImageSharp.Processing.Processors } Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - using (Buffer amounts = new Buffer(width)) - { - int offsetY = y - startY; - int offsetX = minX - startX; - for (int i = 0; i < width; i++) - { - float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY)); - amounts[i] = (this.options.BlendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1); - } + minY, + maxY, + this.ParallelOptions, + y => + { + using (var amounts = new Buffer(width)) + { + int offsetY = y - startY; + int offsetX = minX - startX; + for (int i = 0; i < width; i++) + { + float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY)); + amounts[i] = (this.options.BlendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1); + } - Span destination = sourcePixels.GetRowSpan(offsetY).Slice(offsetX, width); + Span destination = source.GetRowSpan(offsetY).Slice(offsetX, width); - this.blender.Blend(destination, destination, rowColors, amounts); - } - }); + this.blender.Blend(destination, destination, rowColors, amounts); + } + }); } } } diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs index be431b07d..4dfa41989 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs @@ -58,7 +58,7 @@ namespace ImageSharp.Processing.Processors int startX = sourceRectangle.X; int endX = sourceRectangle.Right; TPixel vignetteColor = this.VignetteColor; - Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2(); + var centre = Rectangle.Center(sourceRectangle).ToVector2(); float rX = this.RadiusX > 0 ? MathF.Min(this.RadiusX, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; float rY = this.RadiusY > 0 ? MathF.Min(this.RadiusY, sourceRectangle.Height * .5F) : sourceRectangle.Height * .5F; float maxDistance = MathF.Sqrt((rX * rX) + (rY * rY)); @@ -81,8 +81,7 @@ namespace ImageSharp.Processing.Processors } int width = maxX - minX; - using (Buffer rowColors = new Buffer(width)) - using (PixelAccessor sourcePixels = source.Lock()) + using (var rowColors = new Buffer(width)) { for (int i = 0; i < width; i++) { @@ -95,7 +94,7 @@ namespace ImageSharp.Processing.Processors this.ParallelOptions, y => { - using (Buffer amounts = new Buffer(width)) + using (var amounts = new Buffer(width)) { int offsetY = y - startY; int offsetX = minX - startX; @@ -105,7 +104,7 @@ namespace ImageSharp.Processing.Processors amounts[i] = (this.options.BlendPercentage * (.9F * (distance / maxDistance))).Clamp(0, 1); } - Span destination = sourcePixels.GetRowSpan(offsetY).Slice(offsetX, width); + Span destination = source.GetRowSpan(offsetY).Slice(offsetX, width); this.blender.Blend(destination, destination, rowColors, amounts); } From 9dc1009d1b7e599349048076a8a70c6429197375 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 15:15:49 +1000 Subject: [PATCH 20/84] Optimize Crop --- .../Processors/Transforms/CropProcessor.cs | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs index b67ef5bf1..ade5fa830 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs @@ -7,7 +7,7 @@ namespace ImageSharp.Processing.Processors { using System; using System.Threading.Tasks; - + using ImageSharp.Memory; using ImageSharp.PixelFormats; /// @@ -44,22 +44,18 @@ namespace ImageSharp.Processing.Processors int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X); int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right); - using (PixelAccessor targetPixels = new PixelAccessor(this.CropRectangle.Width, this.CropRectangle.Height)) + using (var targetPixels = new PixelAccessor(this.CropRectangle.Width, this.CropRectangle.Height)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - for (int x = minX; x < maxX; x++) - { - targetPixels[x - minX, y - minY] = sourcePixels[x, y]; - } - }); - } + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + Span sourceRow = source.GetRowSpan(minX, y); + Span targetRow = targetPixels.GetRowSpan(y - minY); + SpanHelper.Copy(sourceRow, targetRow, maxX - minX); + }); source.SwapPixelsBuffers(targetPixels); } From 10e84c94d2081454194d9b88ed748d00976c5b63 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 15:19:52 +1000 Subject: [PATCH 21/84] Fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c672d7ca3..561768199 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ using (Image image = Image.Load(stream)) } ``` -Setting individual pixel values can perfomed as follows: +Setting individual pixel values can be perfomed as follows: ```csharp // Individual pixels From 3b48b116234f9d90b9ab878ac4536c101ae65853 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 15:34:24 +1000 Subject: [PATCH 22/84] Optimize EntroyCrop --- src/ImageSharp/Common/Helpers/ImageMaths.cs | 25 +++++++++------------ 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index 6c8c62039..9c4dee503 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -157,10 +157,10 @@ namespace ImageSharp { int width = bitmap.Width; int height = bitmap.Height; - Point topLeft = default(Point); - Point bottomRight = default(Point); + var topLeft = default(Point); + var bottomRight = default(Point); - Func, int, int, float, bool> delegateFunc; + Func, int, int, float, bool> delegateFunc; // Determine which channel to check against switch (channel) @@ -182,7 +182,7 @@ namespace ImageSharp break; } - int GetMinY(PixelAccessor pixels) + int GetMinY(ImageBase pixels) { for (int y = 0; y < height; y++) { @@ -198,7 +198,7 @@ namespace ImageSharp return 0; } - int GetMaxY(PixelAccessor pixels) + int GetMaxY(ImageBase pixels) { for (int y = height - 1; y > -1; y--) { @@ -214,7 +214,7 @@ namespace ImageSharp return height; } - int GetMinX(PixelAccessor pixels) + int GetMinX(ImageBase pixels) { for (int x = 0; x < width; x++) { @@ -230,7 +230,7 @@ namespace ImageSharp return 0; } - int GetMaxX(PixelAccessor pixels) + int GetMaxX(ImageBase pixels) { for (int x = width - 1; x > -1; x--) { @@ -246,13 +246,10 @@ namespace ImageSharp return height; } - using (PixelAccessor bitmapPixels = bitmap.Lock()) - { - topLeft.Y = GetMinY(bitmapPixels); - topLeft.X = GetMinX(bitmapPixels); - bottomRight.Y = (GetMaxY(bitmapPixels) + 1).Clamp(0, height); - bottomRight.X = (GetMaxX(bitmapPixels) + 1).Clamp(0, width); - } + topLeft.Y = GetMinY(bitmap); + topLeft.X = GetMinX(bitmap); + bottomRight.Y = (GetMaxY(bitmap) + 1).Clamp(0, height); + bottomRight.X = (GetMaxX(bitmap) + 1).Clamp(0, width); return GetBoundingRectangle(topLeft, bottomRight); } From 8b84e6653b00e4bfe42787bb32a099289948d8fe Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 16:59:21 +1000 Subject: [PATCH 23/84] Optimize Flip --- .../Processors/Transforms/FlipProcessor.cs | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs index 2faf77905..d4303c455 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs @@ -8,6 +8,7 @@ namespace ImageSharp.Processing.Processors using System; using System.Threading.Tasks; + using ImageSharp.Memory; using ImageSharp.PixelFormats; /// @@ -57,24 +58,23 @@ namespace ImageSharp.Processing.Processors int height = source.Height; int halfHeight = (int)Math.Ceiling(source.Height * .5F); - using (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - 0, - halfHeight, - this.ParallelOptions, - y => - { - for (int x = 0; x < width; x++) - { - int newY = height - y - 1; - targetPixels[x, y] = sourcePixels[x, newY]; - targetPixels[x, newY] = sourcePixels[x, y]; - } - }); - } + Parallel.For( + 0, + halfHeight, + this.ParallelOptions, + y => + { + int newY = height - y - 1; + Span sourceRow = source.GetRowSpan(y); + Span altSourceRow = source.GetRowSpan(newY); + Span targetRow = targetPixels.GetRowSpan(y); + Span altTargetRow = targetPixels.GetRowSpan(newY); + + sourceRow.CopyTo(altTargetRow); + altSourceRow.CopyTo(targetRow); + }); source.SwapPixelsBuffers(targetPixels); } @@ -91,24 +91,24 @@ namespace ImageSharp.Processing.Processors int height = source.Height; int halfWidth = (int)Math.Ceiling(width * .5F); - using (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => + Parallel.For( + 0, + height, + this.ParallelOptions, + y => + { + Span sourceRow = source.GetRowSpan(y); + Span targetRow = targetPixels.GetRowSpan(y); + + for (int x = 0; x < halfWidth; x++) { - for (int x = 0; x < halfWidth; x++) - { - int newX = width - x - 1; - targetPixels[x, y] = sourcePixels[newX, y]; - targetPixels[newX, y] = sourcePixels[x, y]; - } - }); - } + int newX = width - x - 1; + targetRow[x] = sourceRow[newX]; + targetRow[newX] = sourceRow[x]; + } + }); source.SwapPixelsBuffers(targetPixels); } From 2eb849957c2b57e68508b33ddeeb02dcfdb4575a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 17:30:14 +1000 Subject: [PATCH 24/84] Optimize Resize --- .../ResamplingWeightedProcessor.Weights.cs | 5 ++ .../Transforms/ResamplingWeightedProcessor.cs | 4 +- .../Processors/Transforms/ResizeProcessor.cs | 66 +++++++++---------- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs index d49f37803..b5266c9bd 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs @@ -1,3 +1,8 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + namespace ImageSharp.Processing.Processors { using System; diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs index e2f77d812..757b0889a 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs @@ -6,9 +6,7 @@ namespace ImageSharp.Processing.Processors { using System; - using System.Buffers; using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; using ImageSharp.PixelFormats; @@ -90,7 +88,7 @@ namespace ImageSharp.Processing.Processors IResampler sampler = this.Sampler; float radius = MathF.Ceiling(scale * sampler.Radius); - WeightsBuffer result = new WeightsBuffer(sourceSize, destinationSize); + var result = new WeightsBuffer(sourceSize, destinationSize); for (int i = 0; i < destinationSize; i++) { diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs index 61a64f60f..68ff1397d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs @@ -73,26 +73,24 @@ namespace ImageSharp.Processing.Processors float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width; float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height; - using (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - // Y coordinates of source points - int originY = (int)(((y - startY) * heightFactor) + sourceY); + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + // Y coordinates of source points + Span sourceRow = source.GetRowSpan((int)(((y - startY) * heightFactor) + sourceY)); + Span targetRow = targetPixels.GetRowSpan(y); - for (int x = minX; x < maxX; x++) - { - // X coordinates of source points - targetPixels[x, y] = sourcePixels[(int)(((x - startX) * widthFactor) + sourceX), originY]; - } - }); - } + for (int x = minX; x < maxX; x++) + { + // X coordinates of source points + targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; + } + }); // Break out now. source.SwapPixelsBuffers(targetPixels); @@ -106,10 +104,9 @@ namespace ImageSharp.Processing.Processors // are the upper and lower bounds of the source rectangle. // TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed! - using (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - using (Buffer2D firstPassPixels = new Buffer2D(width, source.Height)) + using (var firstPassPixels = new Buffer2D(width, source.Height)) { firstPassPixels.Clear(); @@ -120,21 +117,18 @@ namespace ImageSharp.Processing.Processors y => { // TODO: Without Parallel.For() this buffer object could be reused: - using (Buffer tempRowBuffer = new Buffer(sourcePixels.Width)) + using (var tempRowBuffer = new Buffer(source.Width)) { - Span sourceRow = sourcePixels.GetRowSpan(y); - - PixelOperations.Instance.ToVector4( - sourceRow, - tempRowBuffer, - sourceRow.Length); + Span firstPassRow = firstPassPixels.GetRowSpan(y); + Span sourceRow = source.GetRowSpan(y); + PixelOperations.Instance.ToVector4(sourceRow, tempRowBuffer, sourceRow.Length); if (this.Compand) { for (int x = minX; x < maxX; x++) { WeightsWindow window = this.HorizontalWeights.Weights[x - startX]; - firstPassPixels[x, y] = window.ComputeExpandedWeightedRowSum(tempRowBuffer, sourceX); + firstPassRow[x] = window.ComputeExpandedWeightedRowSum(tempRowBuffer, sourceX); } } else @@ -142,7 +136,7 @@ namespace ImageSharp.Processing.Processors for (int x = minX; x < maxX; x++) { WeightsWindow window = this.HorizontalWeights.Weights[x - startX]; - firstPassPixels[x, y] = window.ComputeWeightedRowSum(tempRowBuffer, sourceX); + firstPassRow[x] = window.ComputeWeightedRowSum(tempRowBuffer, sourceX); } } } @@ -157,6 +151,7 @@ namespace ImageSharp.Processing.Processors { // Ensure offsets are normalised for cropping and padding. WeightsWindow window = this.VerticalWeights.Weights[y - startY]; + Span targetRow = targetPixels.GetRowSpan(y); if (this.Compand) { @@ -165,9 +160,9 @@ namespace ImageSharp.Processing.Processors // Destination color components Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY); destination = destination.Compress(); - TPixel d = default(TPixel); - d.PackFromVector4(destination); - targetPixels[x, y] = d; + + ref TPixel pixel = ref targetRow[x]; + pixel.PackFromVector4(destination); } } else @@ -177,9 +172,8 @@ namespace ImageSharp.Processing.Processors // Destination color components Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY); - TPixel d = default(TPixel); - d.PackFromVector4(destination); - targetPixels[x, y] = d; + ref TPixel pixel = ref targetRow[x]; + pixel.PackFromVector4(destination); } } }); From b87512333d5971305015b40cea1e8ff8e607da1e Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 18:46:27 +1000 Subject: [PATCH 25/84] Optimize Rotate and Skew --- .../Processors/Transforms/RotateProcessor.cs | 94 +++++++++---------- .../Processors/Transforms/SkewProcessor.cs | 34 +++---- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs index fc5d29b06..43dbb53ea 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs @@ -8,7 +8,7 @@ namespace ImageSharp.Processing.Processors using System; using System.Numerics; using System.Threading.Tasks; - + using ImageSharp.Memory; using ImageSharp.PixelFormats; /// @@ -45,26 +45,26 @@ namespace ImageSharp.Processing.Processors int width = this.CanvasRectangle.Width; Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix); - using (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => + Parallel.For( + 0, + height, + this.ParallelOptions, + y => + { + Span targetRow = targetPixels.GetRowSpan(y); + + for (int x = 0; x < width; x++) { - for (int x = 0; x < width; x++) + var transformedPoint = Point.Rotate(new Point(x, y), matrix); + + if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y)) { - Point transformedPoint = Point.Rotate(new Point(x, y), matrix); - if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y)) - { - targetPixels[x, y] = sourcePixels[transformedPoint.X, transformedPoint.Y]; - } + targetRow[x] = source[transformedPoint.X, transformedPoint.Y]; } - }); - } + } + }); source.SwapPixelsBuffers(targetPixels); } @@ -128,7 +128,7 @@ namespace ImageSharp.Processing.Processors int width = source.Width; int height = source.Height; - using (PixelAccessor targetPixels = new PixelAccessor(height, width)) + using (var targetPixels = new PixelAccessor(height, width)) { using (PixelAccessor sourcePixels = source.Lock()) { @@ -161,24 +161,22 @@ namespace ImageSharp.Processing.Processors int width = source.Width; int height = source.Height; - using (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => + Parallel.For( + 0, + height, + this.ParallelOptions, + y => + { + Span sourceRow = source.GetRowSpan(y); + Span targetRow = targetPixels.GetRowSpan(height - y - 1); + + for (int x = 0; x < width; x++) { - for (int x = 0; x < width; x++) - { - int newX = width - x - 1; - int newY = height - y - 1; - targetPixels[newX, newY] = sourcePixels[x, y]; - } - }); - } + targetRow[width - x - 1] = sourceRow[x]; + } + }); source.SwapPixelsBuffers(targetPixels); } @@ -193,23 +191,21 @@ namespace ImageSharp.Processing.Processors int width = source.Width; int height = source.Height; - using (PixelAccessor targetPixels = new PixelAccessor(height, width)) + using (var targetPixels = new PixelAccessor(height, width)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => + Parallel.For( + 0, + height, + this.ParallelOptions, + y => + { + Span sourceRow = source.GetRowSpan(y); + int newX = height - y - 1; + for (int x = 0; x < width; x++) { - for (int x = 0; x < width; x++) - { - int newX = height - y - 1; - targetPixels[newX, x] = sourcePixels[x, y]; - } - }); - } + targetPixels[newX, x] = sourceRow[x]; + } + }); source.SwapPixelsBuffers(targetPixels); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs index 40ea6a94e..7807d0dfc 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs @@ -8,7 +8,7 @@ namespace ImageSharp.Processing.Processors using System; using System.Numerics; using System.Threading.Tasks; - + using ImageSharp.Memory; using ImageSharp.PixelFormats; /// @@ -45,26 +45,26 @@ namespace ImageSharp.Processing.Processors int width = this.CanvasRectangle.Width; Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix); - using (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - 0, - height, - this.ParallelOptions, - y => + Parallel.For( + 0, + height, + this.ParallelOptions, + y => + { + Span targetRow = targetPixels.GetRowSpan(y); + + for (int x = 0; x < width; x++) { - for (int x = 0; x < width; x++) + var transformedPoint = Point.Skew(new Point(x, y), matrix); + + if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y)) { - Point transformedPoint = Point.Skew(new Point(x, y), matrix); - if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y)) - { - targetPixels[x, y] = sourcePixels[transformedPoint.X, transformedPoint.Y]; - } + targetRow[x] = source[transformedPoint.X, transformedPoint.Y]; } - }); - } + } + }); source.SwapPixelsBuffers(targetPixels); } From 0a24d3195f8ab61b61540d0aedb728d23f19c1eb Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 18:46:41 +1000 Subject: [PATCH 26/84] Cleanup --- .../Processing/Processors/Transforms/Matrix3x2Processor.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Matrix3x2Processor.cs b/src/ImageSharp/Processing/Processors/Transforms/Matrix3x2Processor.cs index 3135551f8..4cc03d864 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Matrix3x2Processor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Matrix3x2Processor.cs @@ -5,7 +5,6 @@ namespace ImageSharp.Processing.Processors { - using System; using System.Numerics; using ImageSharp.PixelFormats; @@ -45,8 +44,8 @@ namespace ImageSharp.Processing.Processors /// protected Matrix3x2 GetCenteredMatrix(ImageBase source, Matrix3x2 matrix) { - Matrix3x2 translationToTargetCenter = Matrix3x2.CreateTranslation(-this.CanvasRectangle.Width * .5F, -this.CanvasRectangle.Height * .5F); - Matrix3x2 translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width * .5F, source.Height * .5F); + var translationToTargetCenter = Matrix3x2.CreateTranslation(-this.CanvasRectangle.Width * .5F, -this.CanvasRectangle.Height * .5F); + var translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width * .5F, source.Height * .5F); return (translationToTargetCenter * matrix) * translateToSourceCenter; } } From 6208f27b8a08c86d4c80688faa595d19a2afe5a4 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 25 May 2017 00:19:37 +1000 Subject: [PATCH 27/84] Read spec, fix gifs --- src/ImageSharp/Formats/Gif/GifDecoderCore.cs | 92 +++++++++---------- src/ImageSharp/Formats/Gif/GifEncoderCore.cs | 43 ++++----- .../Sections/GifGraphicsControlExtension.cs | 2 +- .../Quantizers/OctreeQuantizer{TPixel}.cs | 12 ++- 4 files changed, 71 insertions(+), 78 deletions(-) diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 272e4d075..618d268f7 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -191,7 +191,7 @@ namespace ImageSharp.Formats byte packed = this.buffer[8]; - GifImageDescriptor imageDescriptor = new GifImageDescriptor + var imageDescriptor = new GifImageDescriptor { Left = BitConverter.ToInt16(this.buffer, 0), Top = BitConverter.ToInt16(this.buffer, 2), @@ -337,7 +337,7 @@ namespace ImageSharp.Formats private void ReadFrameIndices(GifImageDescriptor imageDescriptor, byte[] indices) { int dataSize = this.currentStream.ReadByte(); - using (LzwDecoder lzwDecoder = new LzwDecoder(this.currentStream)) + using (var lzwDecoder = new LzwDecoder(this.currentStream)) { lzwDecoder.DecodePixels(imageDescriptor.Width, imageDescriptor.Height, dataSize, indices); } @@ -396,62 +396,60 @@ namespace ImageSharp.Formats int interlaceIncrement = 8; // The interlacing line increment int interlaceY = 0; // The current interlaced line - using (PixelAccessor pixelAccessor = image.Lock()) + for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) { - for (int y = descriptor.Top; y < descriptor.Top + descriptor.Height; y++) + // Check if this image is interlaced. + int writeY; // the target y offset to write to + if (descriptor.InterlaceFlag) { - // Check if this image is interlaced. - int writeY; // the target y offset to write to - if (descriptor.InterlaceFlag) + // If so then we read lines at predetermined offsets. + // When an entire image height worth of offset lines has been read we consider this a pass. + // With each pass the number of offset lines changes and the starting line changes. + if (interlaceY >= descriptor.Height) { - // If so then we read lines at predetermined offsets. - // When an entire image height worth of offset lines has been read we consider this a pass. - // With each pass the number of offset lines changes and the starting line changes. - if (interlaceY >= descriptor.Height) + interlacePass++; + switch (interlacePass) { - interlacePass++; - switch (interlacePass) - { - case 1: - interlaceY = 4; - break; - case 2: - interlaceY = 2; - interlaceIncrement = 4; - break; - case 3: - interlaceY = 1; - interlaceIncrement = 2; - break; - } + case 1: + interlaceY = 4; + break; + case 2: + interlaceY = 2; + interlaceIncrement = 4; + break; + case 3: + interlaceY = 1; + interlaceIncrement = 2; + break; } + } - writeY = interlaceY + descriptor.Top; + writeY = interlaceY + descriptor.Top; - interlaceY += interlaceIncrement; - } - else - { - writeY = y; - } + interlaceY += interlaceIncrement; + } + else + { + writeY = y; + } - for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++) - { - int index = indices[i]; + Span rowSpan = image.GetRowSpan(writeY); - if (this.graphicsControlExtension == null || - this.graphicsControlExtension.TransparencyFlag == false || - this.graphicsControlExtension.TransparencyIndex != index) - { - int indexOffset = index * 3; + for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++) + { + int index = indices[i]; - TPixel pixel = default(TPixel); - pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255); - pixelAccessor[x, writeY] = pixel; - } + if (this.graphicsControlExtension == null || + this.graphicsControlExtension.TransparencyFlag == false || + this.graphicsControlExtension.TransparencyIndex != index) + { + int indexOffset = index * 3; - i++; + ref TPixel pixel = ref rowSpan[x]; + pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255); } + + i++; } } @@ -492,7 +490,7 @@ namespace ImageSharp.Formats } else { - using (PixelArea emptyRow = new PixelArea(this.restoreArea.Value.Width, ComponentOrder.Xyzw)) + using (var emptyRow = new PixelArea(this.restoreArea.Value.Width, ComponentOrder.Xyzw)) { using (PixelAccessor pixelAccessor = frame.Lock()) { diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index ad0ecc88f..5ef7ca165 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -137,31 +137,20 @@ namespace ImageSharp.Formats private int GetTransparentIndex(QuantizedImage quantized) where TPixel : struct, IPixel { - // Find the lowest alpha value and make it the transparent index. - int index = 255; - byte alpha = 255; - bool hasEmpty = false; - - // Some images may have more than one quantized pixel returned with an alpha value of zero - // so we should always ignore if we have empty pixels present. - for (int i = 0; i < quantized.Palette.Length; i++) + // Transparent pixels are much more likely to be found at the end of a palette + int index = -1; + for (int i = quantized.Palette.Length - 1; i >= 0; i--) { quantized.Palette[i].ToXyzwBytes(this.buffer, 0); - if (!hasEmpty) + if (this.buffer[3] > 0) { - if (this.buffer[0] == 0 && this.buffer[1] == 0 && this.buffer[2] == 0 && this.buffer[3] == 0) - { - alpha = this.buffer[3]; - index = i; - hasEmpty = true; - } - - if (this.buffer[3] < alpha) - { - alpha = this.buffer[3]; - index = i; - } + continue; + } + else + { + index = i; + break; } } @@ -183,8 +172,8 @@ namespace ImageSharp.Formats /// The pixel format. /// The image to encode. /// The writer to write to the stream with. - /// The transparency index to set the default background index to. - private void WriteLogicalScreenDescriptor(Image image, EndianBinaryWriter writer, int tranparencyIndex) + /// The transparency index to set the default background index to. + private void WriteLogicalScreenDescriptor(Image image, EndianBinaryWriter writer, int transparencyIndex) where TPixel : struct, IPixel { var descriptor = new GifLogicalScreenDescriptor @@ -193,7 +182,7 @@ namespace ImageSharp.Formats Height = (short)image.Height, GlobalColorTableFlag = false, // TODO: Always false for now. GlobalColorTableSize = this.bitDepth - 1, - BackgroundColorIndex = (byte)tranparencyIndex + BackgroundColorIndex = unchecked((byte)transparencyIndex) }; writer.Write((ushort)descriptor.Width); @@ -286,8 +275,8 @@ namespace ImageSharp.Formats var extension = new GifGraphicsControlExtension { DisposalMethod = metaData.DisposalMethod, - TransparencyFlag = true, // TODO: The spec here is unclear. Can we get away with this? - TransparencyIndex = transparencyIndex, + TransparencyFlag = transparencyIndex > -1, + TransparencyIndex = unchecked((byte)transparencyIndex), DelayTime = metaData.FrameDelay }; @@ -306,7 +295,7 @@ namespace ImageSharp.Formats writer.Write(field.Byte); writer.Write((ushort)extension.DelayTime); - writer.Write((byte)extension.TransparencyIndex); + writer.Write(extension.TransparencyIndex); writer.Write(GifConstants.Terminator); } diff --git a/src/ImageSharp/Formats/Gif/Sections/GifGraphicsControlExtension.cs b/src/ImageSharp/Formats/Gif/Sections/GifGraphicsControlExtension.cs index 79d98f5fb..503bd4fdf 100644 --- a/src/ImageSharp/Formats/Gif/Sections/GifGraphicsControlExtension.cs +++ b/src/ImageSharp/Formats/Gif/Sections/GifGraphicsControlExtension.cs @@ -29,7 +29,7 @@ namespace ImageSharp.Formats /// The Transparency Index is such that when encountered, the corresponding pixel /// of the display device is not modified and processing goes on to the next pixel. /// - public int TransparencyIndex { get; set; } + public byte TransparencyIndex { get; set; } /// /// Gets or sets the delay time. diff --git a/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs index bd963c452..e19df4cfa 100644 --- a/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs @@ -36,7 +36,7 @@ namespace ImageSharp.Quantizers /// /// Maximum allowed color depth /// - private int colors; + private byte colors; /// /// The reduced image palette @@ -58,7 +58,7 @@ namespace ImageSharp.Quantizers /// public override QuantizedImage Quantize(ImageBase image, int maxColors) { - this.colors = maxColors.Clamp(1, 255); + this.colors = (byte)maxColors.Clamp(1, 255); this.octree = new Octree(this.GetBitsNeededForColorDepth(this.colors)); this.palette = null; @@ -123,7 +123,7 @@ namespace ImageSharp.Quantizers /// protected override TPixel[] GetPalette() { - return this.palette ?? (this.palette = this.octree.Palletize(Math.Max(this.colors, 1))); + return this.palette ?? (this.palette = this.octree.Palletize(Math.Max(this.colors, (byte)1))); } /// @@ -143,6 +143,12 @@ namespace ImageSharp.Quantizers return this.GetClosestPixel(pixel, this.palette, this.colorMap); } + pixel.ToXyzwBytes(this.pixelBuffer, 0); + if (this.pixelBuffer[3] == 0) + { + return this.colors; + } + return (byte)this.octree.GetPaletteIndex(pixel, this.pixelBuffer); } From fb4a24869daf2723a37aa21f756f4a378b2e4cc0 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 25 May 2017 10:11:16 +1000 Subject: [PATCH 28/84] Remove Span member from ImageBase --- src/ImageSharp/Image/IImageBase{TPixel}.cs | 6 +-- src/ImageSharp/Image/Image.LoadPixelData.cs | 7 ++-- src/ImageSharp/Image/ImageBase{TPixel}.cs | 41 ++++++++----------- src/ImageSharp/Image/PixelAccessor{TPixel}.cs | 2 +- src/ImageSharp/Memory/Buffer2D.cs | 2 +- .../Processors/Filters/GrayscaleTest.cs | 4 +- 6 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/ImageSharp/Image/IImageBase{TPixel}.cs b/src/ImageSharp/Image/IImageBase{TPixel}.cs index f0ab5b033..8b4977b7d 100644 --- a/src/ImageSharp/Image/IImageBase{TPixel}.cs +++ b/src/ImageSharp/Image/IImageBase{TPixel}.cs @@ -16,10 +16,8 @@ namespace ImageSharp where TPixel : struct, IPixel { /// - /// Gets the pixels as an array of the given packed pixel format. - /// Important. Due to the nature in the way this is constructed do not rely on the length - /// of the array for calculations. Use Width * Height. + /// Gets the representation of the pixels as an area of contiguous memory in the given pixel format. /// - TPixel[] Pixels { get; } + Span Pixels { get; } } } \ No newline at end of file diff --git a/src/ImageSharp/Image/Image.LoadPixelData.cs b/src/ImageSharp/Image/Image.LoadPixelData.cs index 75aa318be..7b6a4d668 100644 --- a/src/ImageSharp/Image/Image.LoadPixelData.cs +++ b/src/ImageSharp/Image/Image.LoadPixelData.cs @@ -68,11 +68,10 @@ namespace ImageSharp where TPixel : struct, IPixel { int count = width * height; - Guard.MustBeGreaterThanOrEqualTo(data.Length, width * height, nameof(data)); - var image = new Image(config, width, height); - var dest = new Span(image.Pixels, 0, count); + Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); - SpanHelper.Copy(data, dest, count); + var image = new Image(config, width, height); + SpanHelper.Copy(data, image.Pixels, count); return image; } diff --git a/src/ImageSharp/Image/ImageBase{TPixel}.cs b/src/ImageSharp/Image/ImageBase{TPixel}.cs index 60fcdda48..508c73eb2 100644 --- a/src/ImageSharp/Image/ImageBase{TPixel}.cs +++ b/src/ImageSharp/Image/ImageBase{TPixel}.cs @@ -32,15 +32,12 @@ namespace ImageSharp /// public const int MaxHeight = int.MaxValue; +#pragma warning disable SA1401 // Fields must be private /// - /// The image pixels + /// The image pixels. Not private as Buffer2D requires an array in its constructor. /// - private TPixel[] pixelBuffer; - - /// - /// The span representing the pixel buffer - /// - private Span span; + internal TPixel[] PixelBuffer; +#pragma warning restore SA1401 // Fields must be private /// /// A value indicating whether this instance of the given entity has been disposed. @@ -116,7 +113,7 @@ namespace ImageSharp } /// - public TPixel[] Pixels => this.pixelBuffer; + public Span Pixels => new Span(this.PixelBuffer, 0, this.Width * this.Height); /// public int Width { get; private set; } @@ -147,14 +144,14 @@ namespace ImageSharp get { this.CheckCoordinates(x, y); - return this.pixelBuffer[(y * this.Width) + x]; + return this.PixelBuffer[(y * this.Width) + x]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] set { this.CheckCoordinates(x, y); - this.pixelBuffer[(y * this.Width) + x] = value; + this.PixelBuffer[(y * this.Width) + x] = value; } } @@ -168,7 +165,7 @@ namespace ImageSharp public ref TPixel GetPixelReference(int x, int y) { this.CheckCoordinates(x, y); - return ref this.pixelBuffer[(y * this.Width) + x]; + return ref this.PixelBuffer[(y * this.Width) + x]; } /// @@ -180,7 +177,7 @@ namespace ImageSharp public Span GetRowSpan(int y) { this.CheckCoordinates(y); - return this.span.Slice(y * this.Width, this.Width); + return this.Pixels.Slice(y * this.Width, this.Width); } /// @@ -193,7 +190,7 @@ namespace ImageSharp public Span GetRowSpan(int x, int y) { this.CheckCoordinates(x, y); - return this.span.Slice((y * this.Width) + x, this.Width - x); + return this.Pixels.Slice((y * this.Width) + x, this.Width - x); } /// @@ -237,7 +234,7 @@ namespace ImageSharp /// The target pixel buffer accessor. internal void CopyTo(PixelAccessor target) { - SpanHelper.Copy(this.span, target.PixelBuffer.Span); + SpanHelper.Copy(this.Pixels, target.PixelBuffer.Span); } /// @@ -251,12 +248,11 @@ namespace ImageSharp int newWidth = pixelSource.Width; int newHeight = pixelSource.Height; - // Push my memory into the accessor (which in turn unpins the old puffer ready for the images use) - TPixel[] newPixels = pixelSource.ReturnCurrentColorsAndReplaceThemInternally(this.Width, this.Height, this.pixelBuffer); + // Push my memory into the accessor (which in turn unpins the old buffer ready for the images use) + TPixel[] newPixels = pixelSource.ReturnCurrentColorsAndReplaceThemInternally(this.Width, this.Height, this.PixelBuffer); this.Width = newWidth; this.Height = newHeight; - this.pixelBuffer = newPixels; - this.span = new Span(this.pixelBuffer); + this.PixelBuffer = newPixels; } /// @@ -307,8 +303,7 @@ namespace ImageSharp /// private void RentPixels() { - this.pixelBuffer = PixelDataPool.Rent(this.Width * this.Height); - this.span = new Span(this.pixelBuffer); + this.PixelBuffer = PixelDataPool.Rent(this.Width * this.Height); } /// @@ -316,8 +311,8 @@ namespace ImageSharp /// private void ReturnPixels() { - PixelDataPool.Return(this.pixelBuffer); - this.pixelBuffer = null; + PixelDataPool.Return(this.PixelBuffer); + this.PixelBuffer = null; } /// @@ -325,7 +320,7 @@ namespace ImageSharp /// private void ClearPixels() { - Array.Clear(this.pixelBuffer, 0, this.Width * this.Height); + Array.Clear(this.PixelBuffer, 0, this.Width * this.Height); } /// diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs index 1d776c258..4baae8615 100644 --- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs @@ -48,7 +48,7 @@ namespace ImageSharp Guard.MustBeGreaterThan(image.Width, 0, "image width"); Guard.MustBeGreaterThan(image.Height, 0, "image height"); - this.SetPixelBufferUnsafe(image.Width, image.Height, image.Pixels); + this.SetPixelBufferUnsafe(image.Width, image.Height, image.PixelBuffer); this.ParallelOptions = image.Configuration.ParallelOptions; } diff --git a/src/ImageSharp/Memory/Buffer2D.cs b/src/ImageSharp/Memory/Buffer2D.cs index e5ccfbd19..59cabb1bd 100644 --- a/src/ImageSharp/Memory/Buffer2D.cs +++ b/src/ImageSharp/Memory/Buffer2D.cs @@ -69,7 +69,7 @@ namespace ImageSharp.Memory /// The instance public static Buffer2D CreateClean(int width, int height) { - Buffer2D buffer = new Buffer2D(width, height); + var buffer = new Buffer2D(width, height); buffer.Clear(); return buffer; } diff --git a/tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs index 9a7d87854..2e82191ec 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs @@ -25,9 +25,9 @@ namespace ImageSharp.Tests { image.Grayscale(value); byte[] data = new byte[3]; - foreach (TPixel p in image.Pixels) + for (int i = 0; i < image.Pixels.Length; i++) { - p.ToXyzBytes(data, 0); + image.Pixels[i].ToXyzBytes(data, 0); Assert.Equal(data[0], data[1]); Assert.Equal(data[1], data[2]); } From 06982fbe27f83938fe764fff3ad3053f5336368d Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 25 May 2017 15:42:03 +1000 Subject: [PATCH 29/84] Don't rent so much for non-pixel pools. --- src/ImageSharp/Memory/PixelDataPool{T}.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ImageSharp/Memory/PixelDataPool{T}.cs b/src/ImageSharp/Memory/PixelDataPool{T}.cs index a8b5501cc..643f1c6ca 100644 --- a/src/ImageSharp/Memory/PixelDataPool{T}.cs +++ b/src/ImageSharp/Memory/PixelDataPool{T}.cs @@ -49,12 +49,13 @@ namespace ImageSharp.Memory // ReSharper disable once SuspiciousTypeConversion.Global if (default(T) is IPixel) { - const int MaximumExpectedImageSize = 16384; - return MaximumExpectedImageSize * MaximumExpectedImageSize; + const int MaximumExpectedImageSize = 16384 * 16384; + return MaximumExpectedImageSize; } else { - return int.MaxValue; + const int MaxArrayLength = 1024 * 1024; // Match default pool. + return MaxArrayLength; } } } From c82f117d196133ad51928fa59de3cd86788bf410 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 25 May 2017 19:43:11 +1000 Subject: [PATCH 30/84] Fix broken test --- tests/ImageSharp.Tests/Common/PixelDataPoolTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/Common/PixelDataPoolTests.cs b/tests/ImageSharp.Tests/Common/PixelDataPoolTests.cs index 1291160b2..21e86d434 100644 --- a/tests/ImageSharp.Tests/Common/PixelDataPoolTests.cs +++ b/tests/ImageSharp.Tests/Common/PixelDataPoolTests.cs @@ -44,7 +44,7 @@ namespace ImageSharp.Tests int max = isRawData ? PixelDataPool.CalculateMaxArrayLength() : PixelDataPool.CalculateMaxArrayLength(); - Assert.Equal(max < int.MaxValue, !isRawData); + Assert.Equal(max > 1024 * 1024, !isRawData); } [Fact] From 7559bebf38a447bdda6e0bb1b4f4272c38f061f5 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 25 May 2017 23:13:23 +1000 Subject: [PATCH 31/84] Better Block8x8F clamp --- .../Jpeg/Components/Block8x8F.Generated.cs | 125 ++++++++++++++---- .../Jpeg/Components/Block8x8F.Generated.tt | 38 +++--- .../Formats/Jpeg/Components/Block8x8F.cs | 10 +- 3 files changed, 120 insertions(+), 53 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index 211b66dac..f84dc977f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -5,53 +5,120 @@ // ReSharper disable InconsistentNaming // #pragma warning disable -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - - namespace ImageSharp.Formats.Jpg { + using System.Numerics; + using System.Runtime.CompilerServices; + internal partial struct Block8x8F { - private static readonly Vector4 CMin4 = new Vector4(-128f); - private static readonly Vector4 CMax4 = new Vector4(127f); - private static readonly Vector4 COff4 = new Vector4(128f); + private static readonly Vector4 CMin4 = new Vector4(0F); + private static readonly Vector4 CMax4 = new Vector4(255F); + private static readonly Vector4 COff4 = new Vector4(128F); /// - /// Transpose the block into d + /// Transpose the block into the destination block. /// - /// Destination + /// The destination block [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TransposeInto(ref Block8x8F d) { - d.V0L.X = V0L.X; d.V1L.X = V0L.Y; d.V2L.X = V0L.Z; d.V3L.X = V0L.W; d.V4L.X = V0R.X; d.V5L.X = V0R.Y; d.V6L.X = V0R.Z; d.V7L.X = V0R.W; - d.V0L.Y = V1L.X; d.V1L.Y = V1L.Y; d.V2L.Y = V1L.Z; d.V3L.Y = V1L.W; d.V4L.Y = V1R.X; d.V5L.Y = V1R.Y; d.V6L.Y = V1R.Z; d.V7L.Y = V1R.W; - d.V0L.Z = V2L.X; d.V1L.Z = V2L.Y; d.V2L.Z = V2L.Z; d.V3L.Z = V2L.W; d.V4L.Z = V2R.X; d.V5L.Z = V2R.Y; d.V6L.Z = V2R.Z; d.V7L.Z = V2R.W; - d.V0L.W = V3L.X; d.V1L.W = V3L.Y; d.V2L.W = V3L.Z; d.V3L.W = V3L.W; d.V4L.W = V3R.X; d.V5L.W = V3R.Y; d.V6L.W = V3R.Z; d.V7L.W = V3R.W; - d.V0R.X = V4L.X; d.V1R.X = V4L.Y; d.V2R.X = V4L.Z; d.V3R.X = V4L.W; d.V4R.X = V4R.X; d.V5R.X = V4R.Y; d.V6R.X = V4R.Z; d.V7R.X = V4R.W; - d.V0R.Y = V5L.X; d.V1R.Y = V5L.Y; d.V2R.Y = V5L.Z; d.V3R.Y = V5L.W; d.V4R.Y = V5R.X; d.V5R.Y = V5R.Y; d.V6R.Y = V5R.Z; d.V7R.Y = V5R.W; - d.V0R.Z = V6L.X; d.V1R.Z = V6L.Y; d.V2R.Z = V6L.Z; d.V3R.Z = V6L.W; d.V4R.Z = V6R.X; d.V5R.Z = V6R.Y; d.V6R.Z = V6R.Z; d.V7R.Z = V6R.W; - d.V0R.W = V7L.X; d.V1R.W = V7L.Y; d.V2R.W = V7L.Z; d.V3R.W = V7L.W; d.V4R.W = V7R.X; d.V5R.W = V7R.Y; d.V6R.W = V7R.Z; d.V7R.W = V7R.W; + d.V0L.X = V0L.X; + d.V1L.X = V0L.Y; + d.V2L.X = V0L.Z; + d.V3L.X = V0L.W; + d.V4L.X = V0R.X; + d.V5L.X = V0R.Y; + d.V6L.X = V0R.Z; + d.V7L.X = V0R.W; + + d.V0L.Y = V1L.X; + d.V1L.Y = V1L.Y; + d.V2L.Y = V1L.Z; + d.V3L.Y = V1L.W; + d.V4L.Y = V1R.X; + d.V5L.Y = V1R.Y; + d.V6L.Y = V1R.Z; + d.V7L.Y = V1R.W; + + d.V0L.Z = V2L.X; + d.V1L.Z = V2L.Y; + d.V2L.Z = V2L.Z; + d.V3L.Z = V2L.W; + d.V4L.Z = V2R.X; + d.V5L.Z = V2R.Y; + d.V6L.Z = V2R.Z; + d.V7L.Z = V2R.W; + + d.V0L.W = V3L.X; + d.V1L.W = V3L.Y; + d.V2L.W = V3L.Z; + d.V3L.W = V3L.W; + d.V4L.W = V3R.X; + d.V5L.W = V3R.Y; + d.V6L.W = V3R.Z; + d.V7L.W = V3R.W; + + d.V0R.X = V4L.X; + d.V1R.X = V4L.Y; + d.V2R.X = V4L.Z; + d.V3R.X = V4L.W; + d.V4R.X = V4R.X; + d.V5R.X = V4R.Y; + d.V6R.X = V4R.Z; + d.V7R.X = V4R.W; + + d.V0R.Y = V5L.X; + d.V1R.Y = V5L.Y; + d.V2R.Y = V5L.Z; + d.V3R.Y = V5L.W; + d.V4R.Y = V5R.X; + d.V5R.Y = V5R.Y; + d.V6R.Y = V5R.Z; + d.V7R.Y = V5R.W; + + d.V0R.Z = V6L.X; + d.V1R.Z = V6L.Y; + d.V2R.Z = V6L.Z; + d.V3R.Z = V6L.W; + d.V4R.Z = V6R.X; + d.V5R.Z = V6R.Y; + d.V6R.Z = V6R.Z; + d.V7R.Z = V6R.W; + + d.V0R.W = V7L.X; + d.V1R.W = V7L.Y; + d.V2R.W = V7L.Z; + d.V3R.W = V7L.W; + d.V4R.W = V7R.X; + d.V5R.W = V7R.Y; + d.V6R.W = V7R.Z; + d.V7R.W = V7R.W; } /// /// Level shift by +128, clip to [0, 255] /// - /// Destination + /// The destination block [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void TransformByteConvetibleColorValuesInto(ref Block8x8F d) { - d.V0L = Vector4.Max(Vector4.Min(V0L, CMax4), CMin4) + COff4;d.V0R = Vector4.Max(Vector4.Min(V0R, CMax4), CMin4) + COff4; - d.V1L = Vector4.Max(Vector4.Min(V1L, CMax4), CMin4) + COff4;d.V1R = Vector4.Max(Vector4.Min(V1R, CMax4), CMin4) + COff4; - d.V2L = Vector4.Max(Vector4.Min(V2L, CMax4), CMin4) + COff4;d.V2R = Vector4.Max(Vector4.Min(V2R, CMax4), CMin4) + COff4; - d.V3L = Vector4.Max(Vector4.Min(V3L, CMax4), CMin4) + COff4;d.V3R = Vector4.Max(Vector4.Min(V3R, CMax4), CMin4) + COff4; - d.V4L = Vector4.Max(Vector4.Min(V4L, CMax4), CMin4) + COff4;d.V4R = Vector4.Max(Vector4.Min(V4R, CMax4), CMin4) + COff4; - d.V5L = Vector4.Max(Vector4.Min(V5L, CMax4), CMin4) + COff4;d.V5R = Vector4.Max(Vector4.Min(V5R, CMax4), CMin4) + COff4; - d.V6L = Vector4.Max(Vector4.Min(V6L, CMax4), CMin4) + COff4;d.V6R = Vector4.Max(Vector4.Min(V6R, CMax4), CMin4) + COff4; - d.V7L = Vector4.Max(Vector4.Min(V7L, CMax4), CMin4) + COff4;d.V7R = Vector4.Max(Vector4.Min(V7R, CMax4), CMin4) + COff4; + d.V0L = Vector4.Clamp(V0L + COff4, CMin4, CMax4); + d.V0R = Vector4.Clamp(V0R + COff4, CMin4, CMax4); + d.V1L = Vector4.Clamp(V1L + COff4, CMin4, CMax4); + d.V1R = Vector4.Clamp(V1R + COff4, CMin4, CMax4); + d.V2L = Vector4.Clamp(V2L + COff4, CMin4, CMax4); + d.V2R = Vector4.Clamp(V2R + COff4, CMin4, CMax4); + d.V3L = Vector4.Clamp(V3L + COff4, CMin4, CMax4); + d.V3R = Vector4.Clamp(V3R + COff4, CMin4, CMax4); + d.V4L = Vector4.Clamp(V4L + COff4, CMin4, CMax4); + d.V4R = Vector4.Clamp(V4R + COff4, CMin4, CMax4); + d.V5L = Vector4.Clamp(V5L + COff4, CMin4, CMax4); + d.V5R = Vector4.Clamp(V5R + COff4, CMin4, CMax4); + d.V6L = Vector4.Clamp(V6L + COff4, CMin4, CMax4); + d.V6R = Vector4.Clamp(V6R + COff4, CMin4, CMax4); + d.V7L = Vector4.Clamp(V7L + COff4, CMin4, CMax4); + d.V7R = Vector4.Clamp(V7R + COff4, CMin4, CMax4); } - - } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index be198a6fa..03566acbb 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -11,31 +11,29 @@ <#@ output extension=".cs" #> // #pragma warning disable -using System; -using System.Numerics; -using System.Runtime.CompilerServices; - <# char[] coordz = {'X', 'Y', 'Z', 'W'}; #> - namespace ImageSharp.Formats.Jpg { + using System.Numerics; + using System.Runtime.CompilerServices; + internal partial struct Block8x8F { - private static readonly Vector4 CMin4 = new Vector4(-128f); - private static readonly Vector4 CMax4 = new Vector4(127f); - private static readonly Vector4 COff4 = new Vector4(128f); + private static readonly Vector4 CMin4 = new Vector4(0F); + private static readonly Vector4 CMax4 = new Vector4(255F); + private static readonly Vector4 COff4 = new Vector4(128F); /// - /// Transpose the block into d + /// Transpose the block into the destination block. /// - /// Destination + /// The destination block [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TransposeInto(ref Block8x8F d) { <# - PushIndent(" "); + PushIndent(" "); for (int i = 0; i < 8; i++) { @@ -44,13 +42,16 @@ namespace ImageSharp.Formats.Jpg for (int j = 0; j < 8; j++) { + if(i > 0 && j == 0){ + WriteLine(""); + } + char srcCoord = coordz[j % 4]; char srcSide = (j / 4) % 2 == 0 ? 'L' : 'R'; - - string expression = $"d.V{j}{destSide}.{destCoord} = V{i}{srcSide}.{srcCoord}; "; + + string expression = $"d.V{j}{destSide}.{destCoord} = V{i}{srcSide}.{srcCoord};\r\n"; Write(expression); } - WriteLine(""); } PopIndent(); #> @@ -59,27 +60,24 @@ namespace ImageSharp.Formats.Jpg /// /// Level shift by +128, clip to [0, 255] /// - /// Destination + /// The destination block [MethodImpl(MethodImplOptions.AggressiveInlining)] internal void TransformByteConvetibleColorValuesInto(ref Block8x8F d) { <# - PushIndent(" "); + PushIndent(" "); for (int i = 0; i < 8; i++) { for (int j = 0; j < 2; j++) { char side = j == 0 ? 'L' : 'R'; - Write($"d.V{i}{side} = Vector4.Max(Vector4.Min(V{i}{side}, CMax4), CMin4) + COff4;"); + Write($"d.V{i}{side} = Vector4.Clamp(V{i}{side} + COff4, CMin4, CMax4);\r\n"); } - WriteLine(""); } PopIndent(); #> } - - } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 56466d7a0..130b5856c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -57,6 +57,9 @@ namespace ImageSharp.Formats.Jpg public Vector4 V7R; #pragma warning restore SA1600 // ElementsMustBeDocumented + private static readonly Vector4 NegativeOne = new Vector4(-1); + private static readonly Vector4 Offset = new Vector4(.5F); + /// /// Get/Set scalar elements at a given index /// @@ -402,12 +405,11 @@ namespace ImageSharp.Formats.Jpg [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Vector4 DivideRound(Vector4 dividend, Vector4 divisor) { - // sign(v) = max(min(v, 1), -1) - Vector4 sign = Vector4.Min(dividend, Vector4.One); - sign = Vector4.Max(sign, new Vector4(-1)); + // sign(dividend) = max(min(dividend, 1), -1) + var sign = Vector4.Clamp(dividend, NegativeOne, Vector4.One); // AlmostRound(dividend/divisor) = dividend/divisior + 0.5*sign(dividend) - return (dividend / divisor) + (sign * new Vector4(0.5f)); + return (dividend / divisor) + (sign * Offset); } } } \ No newline at end of file From b033b7d81af37c37ca95f04d6d1d0191fad17e66 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 26 May 2017 15:24:26 +1000 Subject: [PATCH 32/84] Speed up png plus fix encoding bug --- src/ImageSharp/Formats/Png/PngDecoderCore.cs | 74 +++++++++----------- src/ImageSharp/Formats/Png/PngEncoderCore.cs | 40 +++++------ 2 files changed, 51 insertions(+), 63 deletions(-) diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index f8be0f6cc..b18845aaa 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -178,7 +178,7 @@ namespace ImageSharp.Formats /// /// Thrown if the stream does not contain and end chunk. /// - /// + /// /// Thrown if the image is larger than the maximum allowable size. /// /// The decoded image @@ -189,7 +189,6 @@ namespace ImageSharp.Formats this.currentStream = stream; this.currentStream.Skip(8); Image image = null; - PixelAccessor pixels = null; try { using (var deframeStream = new ZlibInflateStream(this.currentStream)) @@ -211,11 +210,11 @@ namespace ImageSharp.Formats case PngChunkTypes.Data: if (image == null) { - this.InitializeImage(metadata, out image, out pixels); + this.InitializeImage(metadata, out image); } deframeStream.AllocateNewBytes(currentChunk.Length); - this.ReadScanlines(deframeStream.CompressedStream, pixels); + this.ReadScanlines(deframeStream.CompressedStream, image); stream.Read(this.crcBuffer, 0, 4); break; case PngChunkTypes.Palette: @@ -252,7 +251,6 @@ namespace ImageSharp.Formats } finally { - pixels?.Dispose(); this.scanline?.Dispose(); this.previousScanline?.Dispose(); } @@ -324,8 +322,7 @@ namespace ImageSharp.Formats /// The type the pixels will be /// The metadata information for the image /// The image that we will populate - /// The pixel accessor - private void InitializeImage(ImageMetaData metadata, out Image image, out PixelAccessor pixels) + private void InitializeImage(ImageMetaData metadata, out Image image) where TPixel : struct, IPixel { if (this.header.Width > Image.MaxWidth || this.header.Height > Image.MaxHeight) @@ -334,7 +331,6 @@ namespace ImageSharp.Formats } image = new Image(this.configuration, this.header.Width, this.header.Height, metadata); - pixels = image.Lock(); this.bytesPerPixel = this.CalculateBytesPerPixel(); this.bytesPerScanline = this.CalculateScanlineLength(this.header.Width) + 1; this.bytesPerSample = 1; @@ -398,17 +394,17 @@ namespace ImageSharp.Formats /// /// The pixel format. /// The containing data. - /// The pixel data. - private void ReadScanlines(Stream dataStream, PixelAccessor pixels) + /// The pixel data. + private void ReadScanlines(Stream dataStream, Image image) where TPixel : struct, IPixel { if (this.header.InterlaceMethod == PngInterlaceMode.Adam7) { - this.DecodeInterlacedPixelData(dataStream, pixels); + this.DecodeInterlacedPixelData(dataStream, image); } else { - this.DecodePixelData(dataStream, pixels); + this.DecodePixelData(dataStream, image); } } @@ -417,8 +413,8 @@ namespace ImageSharp.Formats /// /// The pixel format. /// The compressed pixel data stream. - /// The image pixel accessor. - private void DecodePixelData(Stream compressedStream, PixelAccessor pixels) + /// The image to decode to. + private void DecodePixelData(Stream compressedStream, Image image) where TPixel : struct, IPixel { while (this.currentRow < this.header.Height) @@ -462,7 +458,7 @@ namespace ImageSharp.Formats throw new ImageFormatException("Unknown filter type."); } - this.ProcessDefilteredScanline(this.scanline.Array, pixels); + this.ProcessDefilteredScanline(this.scanline.Array, image); Swap(ref this.scanline, ref this.previousScanline); this.currentRow++; @@ -475,8 +471,8 @@ namespace ImageSharp.Formats /// /// The pixel format. /// The compressed pixel data stream. - /// The image pixel accessor. - private void DecodeInterlacedPixelData(Stream compressedStream, PixelAccessor pixels) + /// The current image. + private void DecodeInterlacedPixelData(Stream compressedStream, Image image) where TPixel : struct, IPixel { while (true) @@ -537,7 +533,8 @@ namespace ImageSharp.Formats throw new ImageFormatException("Unknown filter type."); } - this.ProcessInterlacedDefilteredScanline(this.scanline.Array, this.currentRow, pixels, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]); + Span rowSpan = image.GetRowSpan(this.currentRow); + this.ProcessInterlacedDefilteredScanline(this.scanline.Array, rowSpan, Adam7FirstColumn[this.pass], Adam7ColumnIncrement[this.pass]); Swap(ref this.scanline, ref this.previousScanline); @@ -561,12 +558,12 @@ namespace ImageSharp.Formats /// /// The pixel format. /// The de-filtered scanline - /// The image pixels - private void ProcessDefilteredScanline(byte[] defilteredScanline, PixelAccessor pixels) + /// The image + private void ProcessDefilteredScanline(byte[] defilteredScanline, Image pixels) where TPixel : struct, IPixel { var color = default(TPixel); - Span pixelBuffer = pixels.GetRowSpan(this.currentRow); + Span rowSpan = pixels.GetRowSpan(this.currentRow); var scanlineBuffer = new Span(defilteredScanline, 1); switch (this.PngColorType) @@ -578,7 +575,7 @@ namespace ImageSharp.Formats { byte intensity = (byte)(newScanline1[x] * factor); color.PackFromBytes(intensity, intensity, intensity, 255); - pixels[x, this.currentRow] = color; + rowSpan[x] = color; } break; @@ -593,26 +590,26 @@ namespace ImageSharp.Formats byte alpha = defilteredScanline[offset + this.bytesPerSample]; color.PackFromBytes(intensity, intensity, intensity, alpha); - pixels[x, this.currentRow] = color; + rowSpan[x] = color; } break; case PngColorType.Palette: - this.ProcessScanlineFromPalette(defilteredScanline, pixels); + this.ProcessScanlineFromPalette(defilteredScanline, rowSpan); break; case PngColorType.Rgb: - PixelOperations.Instance.PackFromXyzBytes(scanlineBuffer, pixelBuffer, this.header.Width); + PixelOperations.Instance.PackFromXyzBytes(scanlineBuffer, rowSpan, this.header.Width); break; case PngColorType.RgbWithAlpha: - PixelOperations.Instance.PackFromXyzwBytes(scanlineBuffer, pixelBuffer, this.header.Width); + PixelOperations.Instance.PackFromXyzwBytes(scanlineBuffer, rowSpan, this.header.Width); break; } @@ -623,8 +620,8 @@ namespace ImageSharp.Formats /// /// The type of pixel we are expanding to /// The scanline - /// The output pixels - private void ProcessScanlineFromPalette(byte[] defilteredScanline, PixelAccessor pixels) + /// Thecurrent output image row + private void ProcessScanlineFromPalette(byte[] defilteredScanline, Span row) where TPixel : struct, IPixel { byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth); @@ -654,7 +651,7 @@ namespace ImageSharp.Formats color.PackFromBytes(0, 0, 0, 0); } - pixels[x, this.currentRow] = color; + row[x] = color; } } else @@ -669,7 +666,7 @@ namespace ImageSharp.Formats byte b = palette[pixelOffset + 2]; color.PackFromBytes(r, g, b, 255); - pixels[x, this.currentRow] = color; + row[x] = color; } } } @@ -679,11 +676,10 @@ namespace ImageSharp.Formats /// /// The pixel format. /// The de-filtered scanline - /// The current image row. - /// The image pixels + /// The current image row. /// The column start index. Always 0 for none interlaced images. /// The column increment. Always 1 for none interlaced images. - private void ProcessInterlacedDefilteredScanline(byte[] defilteredScanline, int row, PixelAccessor pixels, int pixelOffset = 0, int increment = 1) + private void ProcessInterlacedDefilteredScanline(byte[] defilteredScanline, Span rowSpan, int pixelOffset = 0, int increment = 1) where TPixel : struct, IPixel { var color = default(TPixel); @@ -697,7 +693,7 @@ namespace ImageSharp.Formats { byte intensity = (byte)(newScanline1[o] * factor); color.PackFromBytes(intensity, intensity, intensity, 255); - pixels[x, row] = color; + rowSpan[x] = color; } break; @@ -710,7 +706,7 @@ namespace ImageSharp.Formats byte alpha = defilteredScanline[o + this.bytesPerSample]; color.PackFromBytes(intensity, intensity, intensity, alpha); - pixels[x, row] = color; + rowSpan[x] = color; } break; @@ -742,7 +738,7 @@ namespace ImageSharp.Formats color.PackFromBytes(0, 0, 0, 0); } - pixels[x, row] = color; + rowSpan[x] = color; } } else @@ -757,7 +753,7 @@ namespace ImageSharp.Formats byte b = this.palette[offset + 2]; color.PackFromBytes(r, g, b, 255); - pixels[x, row] = color; + rowSpan[x] = color; } } @@ -772,7 +768,7 @@ namespace ImageSharp.Formats byte b = defilteredScanline[o + (2 * this.bytesPerSample)]; color.PackFromBytes(r, g, b, 255); - pixels[x, row] = color; + rowSpan[x] = color; } break; @@ -787,7 +783,7 @@ namespace ImageSharp.Formats byte a = defilteredScanline[o + (3 * this.bytesPerSample)]; color.PackFromBytes(r, g, b, a); - pixels[x, row] = color; + rowSpan[x] = color; } break; diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 0482b2691..3fcf1fc81 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -220,11 +220,7 @@ namespace ImageSharp.Formats this.WritePhysicalChunk(stream, image); this.WriteGammaChunk(stream); - using (PixelAccessor pixels = image.Lock()) - { - this.WriteDataChunks(pixels, stream); - } - + this.WriteDataChunks(image, stream); this.WriteEndChunk(stream); stream.Flush(); } @@ -302,9 +298,8 @@ namespace ImageSharp.Formats /// Collects a row of grayscale pixels. /// /// The pixel format. - /// The image pixels accessor. - /// The row index. - private void CollectGrayscaleBytes(PixelAccessor pixels, int row) + /// The image row span. + private void CollectGrayscaleBytes(Span rowSpan) where TPixel : struct, IPixel { byte[] rawScanlineArray = this.rawScanline.Array; @@ -316,7 +311,7 @@ namespace ImageSharp.Formats // Convert the color to YCbCr and store the luminance // Optionally store the original color alpha. int offset = x * this.bytesPerPixel; - pixels[x, row].ToXyzwBytes(this.chunkTypeBuffer, 0); + rowSpan[x].ToXyzwBytes(this.chunkTypeBuffer, 0); byte luminance = (byte)((0.299F * this.chunkTypeBuffer[0]) + (0.587F * this.chunkTypeBuffer[1]) + (0.114F * this.chunkTypeBuffer[2])); for (int i = 0; i < this.bytesPerPixel; i++) @@ -337,13 +332,10 @@ namespace ImageSharp.Formats /// Collects a row of true color pixel data. /// /// The pixel format. - /// The image pixel accessor. - /// The row index. - private void CollecTPixelBytes(PixelAccessor pixels, int row) + /// The row span. + private void CollecTPixelBytes(Span rowSpan) where TPixel : struct, IPixel { - Span rowSpan = pixels.GetRowSpan(row); - if (this.bytesPerPixel == 4) { PixelOperations.Instance.ToXyzwBytes(rowSpan, this.rawScanline, this.width); @@ -359,10 +351,10 @@ namespace ImageSharp.Formats /// Each scanline is encoded in the most optimal manner to improve compression. /// /// The pixel format. - /// The image pixel accessor. + /// The row span. /// The row. /// The - private Buffer EncodePixelRow(PixelAccessor pixels, int row) + private Buffer EncodePixelRow(Span rowSpan, int row) where TPixel : struct, IPixel { switch (this.pngColorType) @@ -372,10 +364,10 @@ namespace ImageSharp.Formats break; case PngColorType.Grayscale: case PngColorType.GrayscaleWithAlpha: - this.CollectGrayscaleBytes(pixels, row); + this.CollectGrayscaleBytes(rowSpan); break; default: - this.CollecTPixelBytes(pixels, row); + this.CollecTPixelBytes(rowSpan); break; } @@ -637,17 +629,17 @@ namespace ImageSharp.Formats /// Writes the pixel information to the stream. /// /// The pixel format. - /// The pixel accessor. + /// The image. /// The stream. - private void WriteDataChunks(PixelAccessor pixels, Stream stream) + private void WriteDataChunks(Image pixels, Stream stream) where TPixel : struct, IPixel { this.bytesPerScanline = this.width * this.bytesPerPixel; int resultLength = this.bytesPerScanline + 1; - this.previousScanline = new Buffer(this.bytesPerScanline); - this.rawScanline = new Buffer(this.bytesPerScanline); - this.result = new Buffer(resultLength); + this.previousScanline = Buffer.CreateClean(this.bytesPerScanline); + this.rawScanline = Buffer.CreateClean(this.bytesPerScanline); + this.result = Buffer.CreateClean(resultLength); if (this.pngColorType != PngColorType.Palette) { @@ -667,7 +659,7 @@ namespace ImageSharp.Formats { for (int y = 0; y < this.height; y++) { - Buffer r = this.EncodePixelRow(pixels, y); + Buffer r = this.EncodePixelRow(pixels.GetRowSpan(y), y); deflateStream.Write(r.Array, 0, resultLength); Swap(ref this.rawScanline, ref this.previousScanline); From d17de3f9713b668b1f19d645199917c158cae9b5 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 01:23:01 +1000 Subject: [PATCH 33/84] Point, Size + F variants --- .../Numerics/Matrix3x2Extensions.cs | 72 +++++ src/ImageSharp/Numerics/Point.cs | 210 +++++++------ src/ImageSharp/Numerics/PointF.cs | 289 ++++++++++++++++++ src/ImageSharp/Numerics/Size.cs | 109 ++++++- src/ImageSharp/Numerics/SizeF.cs | 229 ++++++++++++++ .../Processors/Transforms/RotateProcessor.cs | 2 +- .../Processors/Transforms/SkewProcessor.cs | 2 +- .../ImageSharp.Tests/Numerics/PointFTests.cs | 170 +++++++++++ tests/ImageSharp.Tests/Numerics/PointTests.cs | 227 ++++++++++++-- tests/ImageSharp.Tests/Numerics/SizeFTests.cs | 163 ++++++++++ tests/ImageSharp.Tests/Numerics/SizeTests.cs | 187 ++++++++++-- 11 files changed, 1523 insertions(+), 137 deletions(-) create mode 100644 src/ImageSharp/Numerics/Matrix3x2Extensions.cs create mode 100644 src/ImageSharp/Numerics/PointF.cs create mode 100644 src/ImageSharp/Numerics/SizeF.cs create mode 100644 tests/ImageSharp.Tests/Numerics/PointFTests.cs create mode 100644 tests/ImageSharp.Tests/Numerics/SizeFTests.cs diff --git a/src/ImageSharp/Numerics/Matrix3x2Extensions.cs b/src/ImageSharp/Numerics/Matrix3x2Extensions.cs new file mode 100644 index 000000000..f42462402 --- /dev/null +++ b/src/ImageSharp/Numerics/Matrix3x2Extensions.cs @@ -0,0 +1,72 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System.Numerics; + using System.Runtime.CompilerServices; + + /// + /// Extension methods for the struct + /// + public static class Matrix3x2Extensions + { + /// + /// Creates a rotation matrix for the given rotation in degrees and a center point. + /// + /// The angle in degrees + /// The center point + /// The rotation + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix3x2 CreateRotation(float degree, Point centerPoint) + { + float radian = MathF.DegreeToRadian(degree); + return Matrix3x2.CreateRotation(radian, new Vector2(centerPoint.X, centerPoint.Y)); + } + + /// + /// Creates a rotation matrix for the given rotation in degrees and a center point. + /// + /// The angle in degrees + /// The center point + /// The rotation + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix3x2 CreateRotation(float degree, PointF centerPoint) + { + float radian = MathF.DegreeToRadian(degree); + return Matrix3x2.CreateRotation(radian, centerPoint); + } + + /// + /// Creates a skew matrix for the given angle in degrees and a center point. + /// + /// The x-angle in degrees + /// The y-angle in degrees + /// The center point + /// The rotation + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix3x2 CreateSkew(float degreesX, float degreesY, Point centerPoint) + { + float radiansX = MathF.DegreeToRadian(degreesX); + float radiansY = MathF.DegreeToRadian(degreesY); + return Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(centerPoint.X, centerPoint.Y)); + } + + /// + /// Creates a skew matrix for the given angle in degrees and a center point. + /// + /// The x-angle in degrees + /// The y-angle in degrees + /// The rotation + /// The center point + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Matrix3x2 CreateSkew(float degreesX, float degreesY, PointF centerPoint) + { + float radiansX = MathF.DegreeToRadian(degreesX); + float radiansY = MathF.DegreeToRadian(degreesY); + return Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(centerPoint.X, centerPoint.Y)); + } + } +} diff --git a/src/ImageSharp/Numerics/Point.cs b/src/ImageSharp/Numerics/Point.cs index 8d523895f..7c607885f 100644 --- a/src/ImageSharp/Numerics/Point.cs +++ b/src/ImageSharp/Numerics/Point.cs @@ -25,6 +25,17 @@ namespace ImageSharp /// public static readonly Point Empty = default(Point); + /// + /// Initializes a new instance of the struct. + /// + /// The horizontal and vertical position of the point. + public Point(int value) + : this() + { + this.X = LowInt16(value); + this.Y = HighInt16(value); + } + /// /// Initializes a new instance of the struct. /// @@ -38,15 +49,13 @@ namespace ImageSharp } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct from the given . /// - /// - /// The vector representing the width and height. - /// - public Point(Vector2 vector) + /// The size + public Point(Size size) { - this.X = (int)Math.Round(vector.X); - this.Y = (int)Math.Round(vector.Y); + this.X = size.Width; + this.Y = size.Height; } /// @@ -66,42 +75,66 @@ namespace ImageSharp public bool IsEmpty => this.Equals(Empty); /// - /// Computes the sum of adding two points. + /// Creates a with the coordinates of the specified . /// - /// The point on the left hand of the operand. - /// The point on the right hand of the operand. - /// - /// The - /// + /// The point + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator PointF(Point point) + { + return new PointF(point.X, point.Y); + } + + /// + /// Creates a with the coordinates of the specified . + /// + /// The point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point operator +(Point left, Point right) + public static implicit operator Vector2(Point point) { - return new Point(left.X + right.X, left.Y + right.Y); + return new Vector2(point.X, point.Y); } /// - /// Computes the difference left by subtracting one point from another. + /// Creates a with the coordinates of the specified . /// - /// The point on the left hand of the operand. - /// The point on the right hand of the operand. + /// The point + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Size(Point point) + { + return new Size(point.X, point.Y); + } + + /// + /// Translates a by a given . + /// + /// The point on the left hand of the operand. + /// The size on the right hand of the operand. /// /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point operator -(Point left, Point right) + public static Point operator +(Point point, Size size) + { + return Add(point, size); + } + + /// + /// Translates a by the negative of a given . + /// + /// The point on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point operator -(Point point, Size size) { - return new Point(left.X - right.X, left.Y - right.Y); + return Subtract(point, size); } /// /// Compares two objects for equality. /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// + /// The on the left side of the operand. + /// The on the right side of the operand. /// /// True if the current left is equal to the parameter; otherwise, false. /// @@ -114,12 +147,8 @@ namespace ImageSharp /// /// Compares two objects for inequality. /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// + /// The on the left side of the operand. + /// The on the right side of the operand. /// /// True if the current left is unequal to the parameter; otherwise, false. /// @@ -130,76 +159,84 @@ namespace ImageSharp } /// - /// Creates a rotation matrix for the given point and angle. + /// Translates a by the negative of a given . /// - /// The origin point to rotate around - /// Rotation in degrees - /// The rotation - public static Matrix3x2 CreateRotation(Point origin, float degrees) + /// The point on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Add(Point point, Size size) { - float radians = MathF.DegreeToRadian(degrees); - return Matrix3x2.CreateRotation(radians, new Vector2(origin.X, origin.Y)); + return new Point(point.X + size.Width, point.Y + size.Height); } /// - /// Rotates a point around a given a rotation matrix. + /// Translates a by the negative of a given . /// - /// The point to rotate - /// Rotation matrix used - /// The rotated - public static Point Rotate(Point point, Matrix3x2 rotation) + /// The point on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Subtract(Point point, Size size) { - return new Point(Vector2.Transform(new Vector2(point.X, point.Y), rotation)); + return new Point(point.X - size.Width, point.Y - size.Height); } /// - /// Rotates a point around a given origin by the specified angle in degrees. + /// Converts a to a by performing a ceiling operation on all the coordinates. /// - /// The point to rotate - /// The center point to rotate around. - /// The angle in degrees. - /// The rotated - public static Point Rotate(Point point, Point origin, float degrees) + /// The point + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Ceiling(PointF point) { - return new Point(Vector2.Transform(new Vector2(point.X, point.Y), CreateRotation(origin, degrees))); + return new Point((int)MathF.Ceiling(point.X), (int)MathF.Ceiling(point.Y)); } /// - /// Creates a skew matrix for the given point and angle. + /// Converts a to a by performing a round operation on all the coordinates. /// - /// The origin point to rotate around - /// The x-angle in degrees. - /// The y-angle in degrees. - /// The rotation - public static Matrix3x2 CreateSkew(Point origin, float degreesX, float degreesY) + /// The point + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Round(PointF point) { - float radiansX = MathF.DegreeToRadian(degreesX); - float radiansY = MathF.DegreeToRadian(degreesY); - return Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(origin.X, origin.Y)); + return new Point((int)MathF.Round(point.X), (int)MathF.Round(point.Y)); } /// - /// Skews a point using a given a skew matrix. + /// Converts a to a by performing a round operation on all the coordinates. + /// + /// The vector + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Round(Vector2 vector) + { + return new Point((int)MathF.Round(vector.X), (int)MathF.Round(vector.Y)); + } + + /// + /// Rotates a point around the given rotation matrix. /// /// The point to rotate - /// Rotation matrix used + /// Rotation matrix used /// The rotated - public static Point Skew(Point point, Matrix3x2 skew) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Rotate(Point point, Matrix3x2 rotation) { - return new Point(Vector2.Transform(new Vector2(point.X, point.Y), skew)); + return Round(Vector2.Transform(new Vector2(point.X, point.Y), rotation)); } /// - /// Skews a point around a given origin by the specified angles in degrees. + /// Skews a point using the given skew matrix. /// - /// The point to skew. - /// The center point to rotate around. - /// The x-angle in degrees. - /// The y-angle in degrees. - /// The skewed - public static Point Skew(Point point, Point origin, float degreesX, float degreesY) + /// The point to rotate + /// Rotation matrix used + /// The rotated + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Skew(Point point, Matrix3x2 skew) { - return new Point(Vector2.Transform(new Vector2(point.X, point.Y), CreateSkew(origin, degreesX, degreesY))); + return Round(Vector2.Transform(new Vector2(point.X, point.Y), skew)); } /// @@ -216,6 +253,7 @@ namespace ImageSharp /// /// The amount to offset the x-coordinate. /// The amount to offset the y-coordinate. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Offset(int dx, int dy) { this.X += dx; @@ -225,10 +263,11 @@ namespace ImageSharp /// /// Translates this by the specified amount. /// - /// The used offset this . - public void Offset(Point p) + /// The used offset this . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Offset(Point point) { - this.Offset(p.X, p.Y); + this.Offset(point.X, point.Y); } /// @@ -260,23 +299,22 @@ namespace ImageSharp } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(Point other) { return this.X == other.X && this.Y == other.Y; } - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// + private static short HighInt16(int n) => unchecked((short)((n >> 16) & 0xffff)); + + private static short LowInt16(int n) => unchecked((short)(n & 0xffff)); + private int GetHashCode(Point point) { - return point.X ^ point.Y; + unchecked + { + return point.X ^ point.Y; + } } } } \ No newline at end of file diff --git a/src/ImageSharp/Numerics/PointF.cs b/src/ImageSharp/Numerics/PointF.cs new file mode 100644 index 000000000..1b76badb6 --- /dev/null +++ b/src/ImageSharp/Numerics/PointF.cs @@ -0,0 +1,289 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.ComponentModel; + using System.Numerics; + using System.Runtime.CompilerServices; + + /// + /// Represents an ordered pair of single precision floating point x- and y-coordinates that defines a point in + /// a two-dimensional plane. + /// + /// + /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, + /// as it avoids the need to create new values for modification operations. + /// + public struct PointF : IEquatable + { + /// + /// Represents a that has X and Y values set to zero. + /// + public static readonly PointF Empty = default(PointF); + + /// + /// Initializes a new instance of the struct. + /// + /// The horizontal position of the point. + /// The vertical position of the point. + public PointF(float x, float y) + : this() + { + this.X = x; + this.Y = y; + } + + /// + /// Initializes a new instance of the struct from the given . + /// + /// The size + public PointF(SizeF size) + { + this.X = size.Width; + this.Y = size.Height; + } + + /// + /// Gets or sets the x-coordinate of this . + /// + public float X { get; set; } + + /// + /// Gets or sets the y-coordinate of this . + /// + public float Y { get; set; } + + /// + /// Gets a value indicating whether this is empty. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool IsEmpty => this.Equals(Empty); + + /// + /// Creates a with the coordinates of the specified . + /// + /// The vector. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator PointF(Vector2 vector) + { + return new PointF(vector.X, vector.Y); + } + + /// + /// Creates a with the coordinates of the specified . + /// + /// The point. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Vector2(PointF point) + { + return new Vector2(point.X, point.Y); + } + + /// + /// Creates a with the coordinates of the specified by truncating each of the coordinates. + /// + /// The point. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Point(PointF point) + { + return new Point(unchecked((int)MathF.Round(point.X)), unchecked((int)MathF.Round(point.Y))); + } + + /// + /// Translates a by a given . + /// + /// The point on the left hand of the operand. + /// The size on the right hand of the operand. + /// + /// The + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static PointF operator +(PointF point, SizeF size) + { + return Add(point, size); + } + + /// + /// Translates a by the negative of a given . + /// + /// The point on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static PointF operator -(PointF point, SizeF size) + { + return Subtract(point, size); + } + + /// + /// Compares two objects for equality. + /// + /// + /// The on the left side of the operand. + /// + /// + /// The on the right side of the operand. + /// + /// + /// True if the current left is equal to the parameter; otherwise, false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(PointF left, PointF right) + { + return left.Equals(right); + } + + /// + /// Compares two objects for inequality. + /// + /// + /// The on the left side of the operand. + /// + /// + /// The on the right side of the operand. + /// + /// + /// True if the current left is unequal to the parameter; otherwise, false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(PointF left, PointF right) + { + return !left.Equals(right); + } + + /// + /// Translates a by the negative of a given . + /// + /// The point on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static PointF Add(PointF point, SizeF size) + { + return new PointF(point.X + size.Width, point.Y + size.Height); + } + + /// + /// Translates a by the negative of a given . + /// + /// The point on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static PointF Subtract(PointF point, SizeF size) + { + return new PointF(point.X - size.Width, point.Y - size.Height); + } + + /// + /// Rotates a point around the given rotation matrix. + /// + /// The point to rotate + /// Rotation matrix used + /// The rotated + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static PointF Rotate(PointF point, Matrix3x2 rotation) + { + return Vector2.Transform(new Vector2(point.X, point.Y), rotation); + } + + /// + /// Skews a point using the given skew matrix. + /// + /// The point to rotate + /// Rotation matrix used + /// The rotated + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static PointF Skew(PointF point, Matrix3x2 skew) + { + return Vector2.Transform(new Vector2(point.X, point.Y), skew); + } + + /// + /// Translates this by the specified amount. + /// + /// The amount to offset the x-coordinate. + /// The amount to offset the y-coordinate. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Offset(float dx, float dy) + { + this.X += dx; + this.Y += dy; + } + + /// + /// Translates this by the specified amount. + /// + /// The used offset this . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Offset(PointF point) + { + this.Offset(point.X, point.Y); + } + + /// + public override int GetHashCode() + { + return this.GetHashCode(this); + } + + /// + public override string ToString() + { + if (this.IsEmpty) + { + return "PointF [ Empty ]"; + } + + return $"PointF [ X={this.X}, Y={this.Y} ]"; + } + + /// + public override bool Equals(object obj) + { + if (obj is PointF) + { + return this.Equals((PointF)obj); + } + + return false; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(PointF other) + { + return this.X.Equals(other.X) && this.Y.Equals(other.Y); + } + + /// + /// Returns the hash code for this instance. + /// + /// + /// The instance of to return the hash code for. + /// + /// + /// A 32-bit signed integer that is the hash code for this instance. + /// + private int GetHashCode(PointF point) + { + unchecked + { + return point.X.GetHashCode() ^ point.Y.GetHashCode(); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Numerics/Size.cs b/src/ImageSharp/Numerics/Size.cs index bae645ac8..c46247307 100644 --- a/src/ImageSharp/Numerics/Size.cs +++ b/src/ImageSharp/Numerics/Size.cs @@ -23,6 +23,17 @@ namespace ImageSharp /// public static readonly Size Empty = default(Size); + /// + /// Initializes a new instance of the struct. + /// + /// The width and height of the size + public Size(int value) + : this() + { + this.Width = value; + this.Height = value; + } + /// /// Initializes a new instance of the struct. /// @@ -34,6 +45,27 @@ namespace ImageSharp this.Height = height; } + /// + /// Initializes a new instance of the struct. + /// + /// The size + public Size(Size size) + : this() + { + this.Width = size.Width; + this.Height = size.Height; + } + + /// + /// Initializes a new instance of the struct from the given . + /// + /// The point + public Size(Point point) + { + this.Width = point.X; + this.Height = point.Y; + } + /// /// Gets or sets the width of this . /// @@ -50,6 +82,26 @@ namespace ImageSharp [EditorBrowsable(EditorBrowsableState.Never)] public bool IsEmpty => this.Equals(Empty); + /// + /// Creates a with the dimensions of the specified . + /// + /// The point + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator SizeF(Size size) + { + return new SizeF(size.Width, size.Height); + } + + /// + /// Converts the given into a . + /// + /// The size + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Point(Size size) + { + return new Point(size.Width, size.Height); + } + /// /// Computes the sum of adding two sizes. /// @@ -61,7 +113,7 @@ namespace ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Size operator +(Size left, Size right) { - return new Size(left.Width + right.Width, left.Height + right.Height); + return Add(left, right); } /// @@ -75,7 +127,7 @@ namespace ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Size operator -(Size left, Size right) { - return new Size(left.Width - right.Width, left.Height - right.Height); + return Subtract(left, right); } /// @@ -114,6 +166,52 @@ namespace ImageSharp return !left.Equals(right); } + /// + /// Performs vector addition of two objects. + /// + /// The size on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Size Add(Size left, Size right) + { + return new Size(left.Width + right.Width, left.Height + right.Height); + } + + /// + /// Contracts a by another + /// + /// The size on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Size Subtract(Size left, Size right) + { + return new Size(left.Width - right.Width, left.Height - right.Height); + } + + /// + /// Converts a to a by performing a ceiling operation on all the dimensions. + /// + /// The size + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Size Ceiling(SizeF size) + { + return new Size((int)MathF.Ceiling(size.Width), (int)MathF.Ceiling(size.Height)); + } + + /// + /// Converts a to a by performing a round operation on all the dimensions. + /// + /// The size + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Size Round(SizeF size) + { + return new Size((int)MathF.Round(size.Width), (int)MathF.Round(size.Height)); + } + /// public override int GetHashCode() { @@ -132,7 +230,6 @@ namespace ImageSharp } /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(object obj) { if (obj is Size) @@ -144,6 +241,7 @@ namespace ImageSharp } /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(Size other) { return this.Width == other.Width && this.Height == other.Height; @@ -160,7 +258,10 @@ namespace ImageSharp /// private int GetHashCode(Size size) { - return size.Width ^ size.Height; + unchecked + { + return size.Width ^ size.Height; + } } } } diff --git a/src/ImageSharp/Numerics/SizeF.cs b/src/ImageSharp/Numerics/SizeF.cs new file mode 100644 index 000000000..f6b852cfa --- /dev/null +++ b/src/ImageSharp/Numerics/SizeF.cs @@ -0,0 +1,229 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.ComponentModel; + using System.Runtime.CompilerServices; + + /// + /// Stores an ordered pair of single precision floating points, which specify a height and width. + /// + /// + /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, + /// as it avoids the need to create new values for modification operations. + /// + public struct SizeF : IEquatable + { + /// + /// Represents a that has Width and Height values set to zero. + /// + public static readonly SizeF Empty = default(SizeF); + + /// + /// Initializes a new instance of the struct. + /// + /// The width of the size. + /// The height of the size. + public SizeF(float width, float height) + { + this.Width = width; + this.Height = height; + } + + /// + /// Initializes a new instance of the struct. + /// + /// The size + public SizeF(SizeF size) + : this() + { + this.Width = size.Width; + this.Height = size.Height; + } + + /// + /// Initializes a new instance of the struct from the given . + /// + /// The point + public SizeF(PointF point) + { + this.Width = point.X; + this.Height = point.Y; + } + + /// + /// Gets or sets the width of this . + /// + public float Width { get; set; } + + /// + /// Gets or sets the height of this . + /// + public float Height { get; set; } + + /// + /// Gets a value indicating whether this is empty. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool IsEmpty => this.Equals(Empty); + + /// + /// Creates a with the dimensions of the specified by truncating each of the dimensions. + /// + /// The size. + /// + /// The . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Size(SizeF size) + { + return new Size(unchecked((int)size.Width), unchecked((int)size.Height)); + } + + /// + /// Converts the given into a . + /// + /// The size + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator PointF(SizeF size) + { + return new PointF(size.Width, size.Height); + } + + /// + /// Computes the sum of adding two sizes. + /// + /// The size on the left hand of the operand. + /// The size on the right hand of the operand. + /// + /// The + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SizeF operator +(SizeF left, SizeF right) + { + return Add(left, right); + } + + /// + /// Computes the difference left by subtracting one size from another. + /// + /// The size on the left hand of the operand. + /// The size on the right hand of the operand. + /// + /// The + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SizeF operator -(SizeF left, SizeF right) + { + return Subtract(left, right); + } + + /// + /// Compares two objects for equality. + /// + /// The size on the left hand of the operand. + /// The size on the right hand of the operand. + /// + /// True if the current left is equal to the parameter; otherwise, false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(SizeF left, SizeF right) + { + return left.Equals(right); + } + + /// + /// Compares two objects for inequality. + /// + /// The size on the left hand of the operand. + /// The size on the right hand of the operand. + /// + /// True if the current left is unequal to the parameter; otherwise, false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(SizeF left, SizeF right) + { + return !left.Equals(right); + } + + /// + /// Performs vector addition of two objects. + /// + /// The size on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SizeF Add(SizeF left, SizeF right) + { + return new SizeF(left.Width + right.Width, left.Height + right.Height); + } + + /// + /// Contracts a by another + /// + /// The size on the left hand of the operand. + /// The size on the right hand of the operand. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static SizeF Subtract(SizeF left, SizeF right) + { + return new SizeF(left.Width - right.Width, left.Height - right.Height); + } + + /// + public override int GetHashCode() + { + return this.GetHashCode(this); + } + + /// + public override string ToString() + { + if (this.IsEmpty) + { + return "SizeF [ Empty ]"; + } + + return $"SizeF [ Width={this.Width}, Height={this.Height} ]"; + } + + /// + public override bool Equals(object obj) + { + if (obj is SizeF) + { + return this.Equals((SizeF)obj); + } + + return false; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(SizeF other) + { + return this.Width.Equals(other.Width) && this.Height.Equals(other.Height); + } + + /// + /// Returns the hash code for this instance. + /// + /// + /// The instance of to return the hash code for. + /// + /// + /// A 32-bit signed integer that is the hash code for this instance. + /// + private int GetHashCode(SizeF size) + { + unchecked + { + return size.Width.GetHashCode() ^ size.Height.GetHashCode(); + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs index 43dbb53ea..15d7ca641 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs @@ -78,7 +78,7 @@ namespace ImageSharp.Processing.Processors return; } - this.processMatrix = Point.CreateRotation(new Point(0, 0), -this.Angle); + this.processMatrix = Matrix3x2Extensions.CreateRotation(-this.Angle, new Point(0, 0)); if (this.Expand) { this.CreateNewCanvas(sourceRectangle, this.processMatrix); diff --git a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs index 7807d0dfc..264cf4a53 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs @@ -73,7 +73,7 @@ namespace ImageSharp.Processing.Processors /// protected override void BeforeApply(ImageBase source, Rectangle sourceRectangle) { - this.processMatrix = Point.CreateSkew(new Point(0, 0), -this.AngleX, -this.AngleY); + this.processMatrix = Matrix3x2Extensions.CreateSkew(-this.AngleX, -this.AngleY, new Point(0, 0)); if (this.Expand) { this.CreateNewCanvas(sourceRectangle, this.processMatrix); diff --git a/tests/ImageSharp.Tests/Numerics/PointFTests.cs b/tests/ImageSharp.Tests/Numerics/PointFTests.cs new file mode 100644 index 000000000..33de60ca7 --- /dev/null +++ b/tests/ImageSharp.Tests/Numerics/PointFTests.cs @@ -0,0 +1,170 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Numerics +{ + using System; + using System.Globalization; + using System.Reflection; + using Xunit; + + public class PointFTests + { + [Fact] + public void DefaultConstructorTest() + { + Assert.Equal(PointF.Empty, new PointF()); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(float.MinValue, float.MaxValue)] + [InlineData(0.0, 0.0)] + public void NonDefaultConstructorTest(float x, float y) + { + var p1 = new PointF(x, y); + + Assert.Equal(x, p1.X); + Assert.Equal(y, p1.Y); + } + + [Fact] + public void IsEmptyDefaultsTest() + { + Assert.True(PointF.Empty.IsEmpty); + Assert.True(new PointF().IsEmpty); + Assert.True(new PointF(0, 0).IsEmpty); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + public void IsEmptyRandomTest(float x, float y) + { + Assert.False(new PointF(x, y).IsEmpty); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void CoordinatesTest(float x, float y) + { + var p = new PointF(x, y); + Assert.Equal(x, p.X); + Assert.Equal(y, p.Y); + + p.X = 10; + Assert.Equal(10, p.X); + + p.Y = -10.123f; + Assert.Equal(-10.123, p.Y, 3); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue, int.MaxValue, int.MinValue)] + [InlineData(float.MinValue, float.MaxValue, int.MinValue, int.MaxValue)] + [InlineData(0, 0, 0, 0)] + public void ArithmeticTestWithSize(float x, float y, int x1, int y1) + { + var p = new PointF(x, y); + var s = new Size(x1, y1); + + var addExpected = new PointF(x + x1, y + y1); + var subExpected = new PointF(x - x1, y - y1); + Assert.Equal(addExpected, p + s); + Assert.Equal(subExpected, p - s); + Assert.Equal(addExpected, PointF.Add(p, s)); + Assert.Equal(subExpected, PointF.Subtract(p, s)); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MaxValue)] + [InlineData(0, 0)] + public void ArithmeticTestWithSizeF(float x, float y) + { + var p = new PointF(x, y); + var s = new SizeF(y, x); + + var addExpected = new PointF(x + y, y + x); + var subExpected = new PointF(x - y, y - x); + Assert.Equal(addExpected, p + s); + Assert.Equal(subExpected, p - s); + Assert.Equal(addExpected, PointF.Add(p, s)); + Assert.Equal(subExpected, PointF.Subtract(p, s)); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MaxValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void EqualityTest(float x, float y) + { + var pLeft = new PointF(x, y); + var pRight = new PointF(y, x); + + if (x == y) + { + Assert.True(pLeft == pRight); + Assert.False(pLeft != pRight); + Assert.True(pLeft.Equals(pRight)); + Assert.True(pLeft.Equals((object)pRight)); + Assert.Equal(pLeft.GetHashCode(), pRight.GetHashCode()); + return; + } + + Assert.True(pLeft != pRight); + Assert.False(pLeft == pRight); + Assert.False(pLeft.Equals(pRight)); + Assert.False(pLeft.Equals((object)pRight)); + } + + [Fact] + public static void EqualityTest_NotPointF() + { + var point = new PointF(0, 0); + Assert.False(point.Equals(null)); + Assert.False(point.Equals(0)); + + // If PointF implements IEquatable (e.g. in .NET Core), then structs that are implicitly + // convertible to var can potentially be equal. + // See https://github.com/dotnet/corefx/issues/5255. + bool expectsImplicitCastToPointF = typeof(IEquatable).IsAssignableFrom(point.GetType()); + Assert.Equal(expectsImplicitCastToPointF, point.Equals(new Point(0, 0))); + + Assert.False(point.Equals((object)new Point(0, 0))); // No implicit cast + } + + [Fact] + public static void GetHashCodeTest() + { + var point = new PointF(10, 10); + Assert.Equal(point.GetHashCode(), new PointF(10, 10).GetHashCode()); + Assert.NotEqual(point.GetHashCode(), new PointF(20, 10).GetHashCode()); + Assert.NotEqual(point.GetHashCode(), new PointF(10, 20).GetHashCode()); + } + + [Fact] + public void ToStringTest() + { + var p = new PointF(5.1F, -5.123F); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, "PointF [ X={0}, Y={1} ]", p.X, p.Y), p.ToString()); + } + + [Fact] + public void ToStringEmptyTest() + { + var p = new PointF(0, 0); + Assert.Equal("PointF [ Empty ]", p.ToString()); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Numerics/PointTests.cs b/tests/ImageSharp.Tests/Numerics/PointTests.cs index 82b26b946..8eb36b6e8 100644 --- a/tests/ImageSharp.Tests/Numerics/PointTests.cs +++ b/tests/ImageSharp.Tests/Numerics/PointTests.cs @@ -5,46 +5,225 @@ namespace ImageSharp.Tests { + using System.Globalization; using Xunit; - /// - /// Tests the struct. - /// public class PointTests { - /// - /// Tests the equality operators for equality. - /// [Fact] - public void AreEqual() + public void DefaultConstructorTest() { - Point first = new Point(100, 100); - Point second = new Point(100, 100); + Assert.Equal(Point.Empty, new Point()); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void NonDefaultConstructorTest(int x, int y) + { + var p1 = new Point(x, y); + var p2 = new Point(new Size(x, y)); + + Assert.Equal(p1, p2); + } + + [Theory] + [InlineData(int.MaxValue)] + [InlineData(int.MinValue)] + [InlineData(0)] + public void SingleIntConstructorTest(int x) + { + var p1 = new Point(x); + var p2 = new Point(unchecked((short)(x & 0xFFFF)), unchecked((short)((x >> 16) & 0xFFFF))); + + Assert.Equal(p1, p2); + } + + [Fact] + public void IsEmptyDefaultsTest() + { + Assert.True(Point.Empty.IsEmpty); + Assert.True(new Point().IsEmpty); + Assert.True(new Point(0, 0).IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + public void IsEmptyRandomTest(int x, int y) + { + Assert.False(new Point(x, y).IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void CoordinatesTest(int x, int y) + { + var p = new Point(x, y); + Assert.Equal(x, p.X); + Assert.Equal(y, p.Y); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void PointFConversionTest(int x, int y) + { + PointF p = new Point(x, y); + Assert.Equal(new PointF(x, y), p); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void SizeConversionTest(int x, int y) + { + var sz = (Size)new Point(x, y); + Assert.Equal(new Size(x, y), sz); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void ArithmeticTest(int x, int y) + { + Point addExpected, subExpected, p = new Point(x, y); + var s = new Size(y, x); + + unchecked + { + addExpected = new Point(x + y, y + x); + subExpected = new Point(x - y, y - x); + } - Assert.Equal(first, second); + Assert.Equal(addExpected, p + s); + Assert.Equal(subExpected, p - s); + Assert.Equal(addExpected, Point.Add(p, s)); + Assert.Equal(subExpected, Point.Subtract(p, s)); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void PointFMathematicalTest(float x, float y) + { + var pf = new PointF(x, y); + Point pCeiling, pTruncate, pRound; + + unchecked + { + pCeiling = new Point((int)MathF.Ceiling(x), (int)MathF.Ceiling(y)); + pTruncate = new Point((int)x, (int)y); + pRound = new Point((int)MathF.Round(x), (int)MathF.Round(y)); + } + + Assert.Equal(pCeiling, Point.Ceiling(pf)); + Assert.Equal(pRound, Point.Round(pf)); + Assert.Equal(pTruncate, (Point)pf); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void OffsetTest(int x, int y) + { + var p1 = new Point(x, y); + var p2 = new Point(y, x); + + p1.Offset(p2); + + Assert.Equal(unchecked(p2.X + p2.Y), p1.X); + Assert.Equal(p1.X, p1.Y); + + p2.Offset(x, y); + Assert.Equal(p1, p2); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void EqualityTest(int x, int y) + { + var p1 = new Point(x, y); + var p2 = new Point(x / 2 - 1, y / 2 - 1); + var p3 = new Point(x, y); + + Assert.True(p1 == p3); + Assert.True(p1 != p2); + Assert.True(p2 != p3); + + Assert.True(p1.Equals(p3)); + Assert.False(p1.Equals(p2)); + Assert.False(p2.Equals(p3)); + + Assert.True(p1.Equals((object)p3)); + Assert.False(p1.Equals((object)p2)); + Assert.False(p2.Equals((object)p3)); + + Assert.Equal(p1.GetHashCode(), p3.GetHashCode()); + } + + [Fact] + public static void EqualityTest_NotPoint() + { + var point = new Point(0, 0); + Assert.False(point.Equals(null)); + Assert.False(point.Equals(0)); + Assert.False(point.Equals(new PointF(0, 0))); } - /// - /// Tests the equality operators for inequality. - /// [Fact] - public void AreNotEqual() + public static void GetHashCodeTest() { - Point first = new Point(0, 100); - Point second = new Point(100, 100); + var point = new Point(10, 10); + Assert.Equal(point.GetHashCode(), new Point(10, 10).GetHashCode()); + Assert.NotEqual(point.GetHashCode(), new Point(20, 10).GetHashCode()); + Assert.NotEqual(point.GetHashCode(), new Point(10, 20).GetHashCode()); + } - Assert.NotEqual(first, second); + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(1, -2, 3, -4)] + public void ConversionTest(int x, int y, int width, int height) + { + var rect = new Rectangle(x, y, width, height); + RectangleF rectF = rect; + Assert.Equal(x, rectF.X); + Assert.Equal(y, rectF.Y); + Assert.Equal(width, rectF.Width); + Assert.Equal(height, rectF.Height); + } + + [Fact] + public void ToStringTest() + { + var p = new Point(5, -5); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, "Point [ X={0}, Y={1} ]", p.X, p.Y), p.ToString()); } - /// - /// Tests whether the point constructor correctly assign properties. - /// [Fact] - public void ConstructorAssignsProperties() + public void ToStringEmptyTest() { - Point first = new Point(4, 5); - Assert.Equal(4, first.X); - Assert.Equal(5, first.Y); + var p = new Point(0, 0); + Assert.Equal("Point [ Empty ]", p.ToString()); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Numerics/SizeFTests.cs b/tests/ImageSharp.Tests/Numerics/SizeFTests.cs new file mode 100644 index 000000000..dfeee762f --- /dev/null +++ b/tests/ImageSharp.Tests/Numerics/SizeFTests.cs @@ -0,0 +1,163 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests +{ + using System; + using System.Globalization; + using System.Reflection; + using Xunit; + + public class SizeFTests + { + [Fact] + public void DefaultConstructorTest() + { + Assert.Equal(SizeF.Empty, new SizeF()); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void NonDefaultConstructorAndDimensionsTest(float width, float height) + { + var s1 = new SizeF(width, height); + var p1 = new PointF(width, height); + var s2 = new SizeF(s1); + + Assert.Equal(s1, s2); + Assert.Equal(s1, new SizeF(p1)); + Assert.Equal(s2, new SizeF(p1)); + + Assert.Equal(width, s1.Width); + Assert.Equal(height, s1.Height); + + s1.Width = 10; + Assert.Equal(10, s1.Width); + + s1.Height = -10.123f; + Assert.Equal(-10.123, s1.Height, 3); + } + + [Fact] + public void IsEmptyDefaultsTest() + { + Assert.True(SizeF.Empty.IsEmpty); + Assert.True(new SizeF().IsEmpty); + Assert.True(new SizeF(0, 0).IsEmpty); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + public void IsEmptyRandomTest(float width, float height) + { + Assert.False(new SizeF(width, height).IsEmpty); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void ArithmeticTest(float width, float height) + { + var s1 = new SizeF(width, height); + var s2 = new SizeF(height, width); + var addExpected = new SizeF(width + height, width + height); + var subExpected = new SizeF(width - height, height - width); + + Assert.Equal(addExpected, s1 + s2); + Assert.Equal(addExpected, SizeF.Add(s1, s2)); + + Assert.Equal(subExpected, s1 - s2); + Assert.Equal(subExpected, SizeF.Subtract(s1, s2)); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void EqualityTest(float width, float height) + { + var sLeft = new SizeF(width, height); + var sRight = new SizeF(height, width); + + if (width == height) + { + Assert.True(sLeft == sRight); + Assert.False(sLeft != sRight); + Assert.True(sLeft.Equals(sRight)); + Assert.True(sLeft.Equals((object)sRight)); + Assert.Equal(sLeft.GetHashCode(), sRight.GetHashCode()); + return; + } + + Assert.True(sLeft != sRight); + Assert.False(sLeft == sRight); + Assert.False(sLeft.Equals(sRight)); + Assert.False(sLeft.Equals((object)sRight)); + } + + [Fact] + public static void EqualityTest_NotSizeF() + { + var size = new SizeF(0, 0); + Assert.False(size.Equals(null)); + Assert.False(size.Equals(0)); + + // If SizeF implements IEquatable (e.g in .NET Core), then classes that are implicitly + // convertible to SizeF can potentially be equal. + // See https://github.com/dotnet/corefx/issues/5255. + bool expectsImplicitCastToSizeF = typeof(IEquatable).IsAssignableFrom(size.GetType()); + Assert.Equal(expectsImplicitCastToSizeF, size.Equals(new Size(0, 0))); + + Assert.False(size.Equals((object)new Size(0, 0))); // No implicit cast + } + + [Fact] + public static void GetHashCodeTest() + { + var size = new SizeF(10, 10); + Assert.Equal(size.GetHashCode(), new SizeF(10, 10).GetHashCode()); + Assert.NotEqual(size.GetHashCode(), new SizeF(20, 10).GetHashCode()); + Assert.NotEqual(size.GetHashCode(), new SizeF(10, 20).GetHashCode()); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void ConversionTest(float width, float height) + { + var s1 = new SizeF(width, height); + var p1 = (PointF)s1; + var s2 = new Size(unchecked((int)width), unchecked((int)height)); + + Assert.Equal(new PointF(width, height), p1); + Assert.Equal(p1, (PointF)s1); + Assert.Equal(s2, (Size)s1); + } + + [Fact] + public void ToStringTest() + { + var sz = new SizeF(10, 5); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, "SizeF [ Width={0}, Height={1} ]", sz.Width, sz.Height), sz.ToString()); + } + + [Fact] + public void ToStringTestEmpty() + { + var sz = new SizeF(0, 0); + Assert.Equal("SizeF [ Empty ]", sz.ToString()); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Numerics/SizeTests.cs b/tests/ImageSharp.Tests/Numerics/SizeTests.cs index 29eb768d9..010cdad3c 100644 --- a/tests/ImageSharp.Tests/Numerics/SizeTests.cs +++ b/tests/ImageSharp.Tests/Numerics/SizeTests.cs @@ -5,6 +5,7 @@ namespace ImageSharp.Tests { + using System.Globalization; using Xunit; /// @@ -12,39 +13,183 @@ namespace ImageSharp.Tests /// public class SizeTests { - /// - /// Tests the equality operators for equality. - /// [Fact] - public void AreEqual() + public void DefaultConstructorTest() { - Size first = new Size(100, 100); - Size second = new Size(100, 100); + Assert.Equal(Size.Empty, new Size()); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void NonDefaultConstructorTest(int width, int height) + { + var s1 = new Size(width, height); + var s2 = new Size(new Point(width, height)); - Assert.Equal(first, second); + Assert.Equal(s1, s2); + + s1.Width = 10; + Assert.Equal(10, s1.Width); + + s1.Height = -10; + Assert.Equal(-10, s1.Height); } - /// - /// Tests the equality operators for inequality. - /// [Fact] - public void AreNotEqual() + public void IsEmptyDefaultsTest() + { + Assert.True(Size.Empty.IsEmpty); + Assert.True(new Size().IsEmpty); + Assert.True(new Size(0, 0).IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + public void IsEmptyRandomTest(int width, int height) + { + Assert.False(new Size(width, height).IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void DimensionsTest(int width, int height) { - Size first = new Size(0, 100); - Size second = new Size(100, 100); + var p = new Size(width, height); + Assert.Equal(width, p.Width); + Assert.Equal(height, p.Height); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void PointFConversionTest(int width, int height) + { + SizeF sz = new Size(width, height); + Assert.Equal(new SizeF(width, height), sz); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void SizeConversionTest(int width, int height) + { + var sz = (Point)new Size(width, height); + Assert.Equal(new Point(width, height), sz); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void ArithmeticTest(int width, int height) + { + var sz1 = new Size(width, height); + var sz2 = new Size(height, width); + Size addExpected, subExpected; + + unchecked + { + addExpected = new Size(width + height, height + width); + subExpected = new Size(width - height, height - width); + } + + Assert.Equal(addExpected, sz1 + sz2); + Assert.Equal(subExpected, sz1 - sz2); + Assert.Equal(addExpected, Size.Add(sz1, sz2)); + Assert.Equal(subExpected, Size.Subtract(sz1, sz2)); + } - Assert.NotEqual(first, second); + [Theory] + [InlineData(float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MinValue)] + [InlineData(float.MaxValue, float.MaxValue)] + [InlineData(0, 0)] + public void PointFMathematicalTest(float width, float height) + { + var szF = new SizeF(width, height); + Size pCeiling, pTruncate, pRound; + + unchecked + { + pCeiling = new Size((int)MathF.Ceiling(width), (int)MathF.Ceiling(height)); + pTruncate = new Size((int)width, (int)height); + pRound = new Size((int)MathF.Round(width), (int)MathF.Round(height)); + } + + Assert.Equal(pCeiling, Size.Ceiling(szF)); + Assert.Equal(pRound, Size.Round(szF)); + Assert.Equal(pTruncate, (Size)szF); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue)] + [InlineData(int.MinValue, int.MinValue)] + [InlineData(int.MaxValue, int.MaxValue)] + [InlineData(0, 0)] + public void EqualityTest(int width, int height) + { + var p1 = new Size(width, height); + var p2 = new Size(unchecked(width - 1), unchecked(height - 1)); + var p3 = new Size(width, height); + + Assert.True(p1 == p3); + Assert.True(p1 != p2); + Assert.True(p2 != p3); + + Assert.True(p1.Equals(p3)); + Assert.False(p1.Equals(p2)); + Assert.False(p2.Equals(p3)); + + Assert.True(p1.Equals((object)p3)); + Assert.False(p1.Equals((object)p2)); + Assert.False(p2.Equals((object)p3)); + + Assert.Equal(p1.GetHashCode(), p3.GetHashCode()); + } + + [Fact] + public static void EqualityTest_NotSize() + { + var size = new Size(0, 0); + Assert.False(size.Equals(null)); + Assert.False(size.Equals(0)); + Assert.False(size.Equals(new SizeF(0, 0))); + } + + [Fact] + public static void GetHashCodeTest() + { + var size = new Size(10, 10); + Assert.Equal(size.GetHashCode(), new Size(10, 10).GetHashCode()); + Assert.NotEqual(size.GetHashCode(), new Size(20, 10).GetHashCode()); + Assert.NotEqual(size.GetHashCode(), new Size(10, 20).GetHashCode()); + } + + [Fact] + public void ToStringTest() + { + var sz = new Size(10, 5); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, "Size [ Width={0}, Height={1} ]", sz.Width, sz.Height), sz.ToString()); } - /// - /// Tests whether the size constructor correctly assign properties. - /// [Fact] - public void ConstructorAssignsProperties() + public void ToStringTestEmpty() { - Size first = new Size(4, 5); - Assert.Equal(4, first.Width); - Assert.Equal(5, first.Height); + var sz = new Size(0, 0); + Assert.Equal("Size [ Empty ]", sz.ToString()); } } } \ No newline at end of file From d4a10f9d3ea93e59d09e991587ee70930a48e7a6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 10:25:15 +1000 Subject: [PATCH 34/84] Cleanup --- src/ImageSharp/Numerics/Point.cs | 120 ++++-------------- src/ImageSharp/Numerics/PointF.cs | 88 +++---------- src/ImageSharp/Numerics/Size.cs | 88 ++++--------- src/ImageSharp/Numerics/SizeF.cs | 72 ++--------- .../Processors/Overlays/GlowProcessor.cs | 2 +- .../Processors/Overlays/VignetteProcessor.cs | 2 +- tests/ImageSharp.Benchmarks/Samplers/Glow.cs | 2 +- 7 files changed, 80 insertions(+), 294 deletions(-) diff --git a/src/ImageSharp/Numerics/Point.cs b/src/ImageSharp/Numerics/Point.cs index 7c607885f..4d43a83af 100644 --- a/src/ImageSharp/Numerics/Point.cs +++ b/src/ImageSharp/Numerics/Point.cs @@ -79,30 +79,21 @@ namespace ImageSharp /// /// The point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator PointF(Point point) - { - return new PointF(point.X, point.Y); - } + public static implicit operator PointF(Point point) => new PointF(point.X, point.Y); /// /// Creates a with the coordinates of the specified . /// /// The point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Vector2(Point point) - { - return new Vector2(point.X, point.Y); - } + public static implicit operator Vector2(Point point) => new Vector2(point.X, point.Y); /// /// Creates a with the coordinates of the specified . /// /// The point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator Size(Point point) - { - return new Size(point.X, point.Y); - } + public static explicit operator Size(Point point) => new Size(point.X, point.Y); /// /// Translates a by a given . @@ -113,10 +104,7 @@ namespace ImageSharp /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point operator +(Point point, Size size) - { - return Add(point, size); - } + public static Point operator +(Point point, Size size) => Add(point, size); /// /// Translates a by the negative of a given . @@ -125,10 +113,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point operator -(Point point, Size size) - { - return Subtract(point, size); - } + public static Point operator -(Point point, Size size) => Subtract(point, size); /// /// Compares two objects for equality. @@ -139,10 +124,7 @@ namespace ImageSharp /// True if the current left is equal to the parameter; otherwise, false. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Point left, Point right) - { - return left.Equals(right); - } + public static bool operator ==(Point left, Point right) => left.Equals(right); /// /// Compares two objects for inequality. @@ -153,10 +135,7 @@ namespace ImageSharp /// True if the current left is unequal to the parameter; otherwise, false. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(Point left, Point right) - { - return !left.Equals(right); - } + public static bool operator !=(Point left, Point right) => !left.Equals(right); /// /// Translates a by the negative of a given . @@ -165,10 +144,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Add(Point point, Size size) - { - return new Point(point.X + size.Width, point.Y + size.Height); - } + public static Point Add(Point point, Size size) => new Point(unchecked(point.X + size.Width), unchecked(point.Y + size.Height)); /// /// Translates a by the negative of a given . @@ -177,10 +153,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Subtract(Point point, Size size) - { - return new Point(point.X - size.Width, point.Y - size.Height); - } + public static Point Subtract(Point point, Size size) => new Point(unchecked(point.X - size.Width), unchecked(point.Y - size.Height)); /// /// Converts a to a by performing a ceiling operation on all the coordinates. @@ -188,10 +161,7 @@ namespace ImageSharp /// The point /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Ceiling(PointF point) - { - return new Point((int)MathF.Ceiling(point.X), (int)MathF.Ceiling(point.Y)); - } + public static Point Ceiling(PointF point) => new Point(unchecked((int)MathF.Ceiling(point.X)), unchecked((int)MathF.Ceiling(point.Y))); /// /// Converts a to a by performing a round operation on all the coordinates. @@ -199,10 +169,15 @@ namespace ImageSharp /// The point /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Round(PointF point) - { - return new Point((int)MathF.Round(point.X), (int)MathF.Round(point.Y)); - } + public static Point Round(PointF point) => new Point(unchecked((int)MathF.Round(point.X)), unchecked((int)MathF.Round(point.Y))); + + /// + /// Converts a to a by performing a truncate operation on all the coordinates. + /// + /// The point + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Truncate(PointF point) => new Point(unchecked((int)point.X), unchecked((int)point.Y)); /// /// Converts a to a by performing a round operation on all the coordinates. @@ -210,10 +185,7 @@ namespace ImageSharp /// The vector /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Round(Vector2 vector) - { - return new Point((int)MathF.Round(vector.X), (int)MathF.Round(vector.Y)); - } + public static Point Round(Vector2 vector) => new Point(unchecked((int)MathF.Round(vector.X)), unchecked((int)MathF.Round(vector.Y))); /// /// Rotates a point around the given rotation matrix. @@ -222,10 +194,7 @@ namespace ImageSharp /// Rotation matrix used /// The rotated [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Rotate(Point point, Matrix3x2 rotation) - { - return Round(Vector2.Transform(new Vector2(point.X, point.Y), rotation)); - } + public static Point Rotate(Point point, Matrix3x2 rotation) => Round(Vector2.Transform(new Vector2(point.X, point.Y), rotation)); /// /// Skews a point using the given skew matrix. @@ -234,19 +203,7 @@ namespace ImageSharp /// Rotation matrix used /// The rotated [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Point Skew(Point point, Matrix3x2 skew) - { - return Round(Vector2.Transform(new Vector2(point.X, point.Y), skew)); - } - - /// - /// Gets a representation for this . - /// - /// A representation for this object. - public Vector2 ToVector2() - { - return new Vector2(this.X, this.Y); - } + public static Point Skew(Point point, Matrix3x2 skew) => Round(Vector2.Transform(new Vector2(point.X, point.Y), skew)); /// /// Translates this by the specified amount. @@ -265,16 +222,10 @@ namespace ImageSharp /// /// The used offset this . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Offset(Point point) - { - this.Offset(point.X, point.Y); - } + public void Offset(Point point) => this.Offset(point.X, point.Y); /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } + public override int GetHashCode() => this.GetHashCode(this); /// public override string ToString() @@ -288,33 +239,16 @@ namespace ImageSharp } /// - public override bool Equals(object obj) - { - if (obj is Point) - { - return this.Equals((Point)obj); - } - - return false; - } + public override bool Equals(object obj) => obj is Point && this.Equals((Point)obj); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(Point other) - { - return this.X == other.X && this.Y == other.Y; - } + public bool Equals(Point other) => this.X == other.X && this.Y == other.Y; private static short HighInt16(int n) => unchecked((short)((n >> 16) & 0xffff)); private static short LowInt16(int n) => unchecked((short)(n & 0xffff)); - private int GetHashCode(Point point) - { - unchecked - { - return point.X ^ point.Y; - } - } + private int GetHashCode(Point point) => point.X ^ point.Y; } } \ No newline at end of file diff --git a/src/ImageSharp/Numerics/PointF.cs b/src/ImageSharp/Numerics/PointF.cs index 1b76badb6..cbe5c7f48 100644 --- a/src/ImageSharp/Numerics/PointF.cs +++ b/src/ImageSharp/Numerics/PointF.cs @@ -71,10 +71,7 @@ namespace ImageSharp /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator PointF(Vector2 vector) - { - return new PointF(vector.X, vector.Y); - } + public static implicit operator PointF(Vector2 vector) => new PointF(vector.X, vector.Y); /// /// Creates a with the coordinates of the specified . @@ -84,10 +81,7 @@ namespace ImageSharp /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Vector2(PointF point) - { - return new Vector2(point.X, point.Y); - } + public static implicit operator Vector2(PointF point) => new Vector2(point.X, point.Y); /// /// Creates a with the coordinates of the specified by truncating each of the coordinates. @@ -97,10 +91,7 @@ namespace ImageSharp /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator Point(PointF point) - { - return new Point(unchecked((int)MathF.Round(point.X)), unchecked((int)MathF.Round(point.Y))); - } + public static explicit operator Point(PointF point) => Point.Truncate(point); /// /// Translates a by a given . @@ -111,10 +102,7 @@ namespace ImageSharp /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF operator +(PointF point, SizeF size) - { - return Add(point, size); - } + public static PointF operator +(PointF point, SizeF size) => Add(point, size); /// /// Translates a by the negative of a given . @@ -123,10 +111,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF operator -(PointF point, SizeF size) - { - return Subtract(point, size); - } + public static PointF operator -(PointF point, SizeF size) => Subtract(point, size); /// /// Compares two objects for equality. @@ -141,10 +126,7 @@ namespace ImageSharp /// True if the current left is equal to the parameter; otherwise, false. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(PointF left, PointF right) - { - return left.Equals(right); - } + public static bool operator ==(PointF left, PointF right) => left.Equals(right); /// /// Compares two objects for inequality. @@ -159,10 +141,7 @@ namespace ImageSharp /// True if the current left is unequal to the parameter; otherwise, false. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(PointF left, PointF right) - { - return !left.Equals(right); - } + public static bool operator !=(PointF left, PointF right) => !left.Equals(right); /// /// Translates a by the negative of a given . @@ -171,10 +150,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Add(PointF point, SizeF size) - { - return new PointF(point.X + size.Width, point.Y + size.Height); - } + public static PointF Add(PointF point, SizeF size) => new PointF(point.X + size.Width, point.Y + size.Height); /// /// Translates a by the negative of a given . @@ -183,10 +159,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Subtract(PointF point, SizeF size) - { - return new PointF(point.X - size.Width, point.Y - size.Height); - } + public static PointF Subtract(PointF point, SizeF size) => new PointF(point.X - size.Width, point.Y - size.Height); /// /// Rotates a point around the given rotation matrix. @@ -195,10 +168,7 @@ namespace ImageSharp /// Rotation matrix used /// The rotated [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Rotate(PointF point, Matrix3x2 rotation) - { - return Vector2.Transform(new Vector2(point.X, point.Y), rotation); - } + public static PointF Rotate(PointF point, Matrix3x2 rotation) => Vector2.Transform(new Vector2(point.X, point.Y), rotation); /// /// Skews a point using the given skew matrix. @@ -207,10 +177,7 @@ namespace ImageSharp /// Rotation matrix used /// The rotated [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static PointF Skew(PointF point, Matrix3x2 skew) - { - return Vector2.Transform(new Vector2(point.X, point.Y), skew); - } + public static PointF Skew(PointF point, Matrix3x2 skew) => Vector2.Transform(new Vector2(point.X, point.Y), skew); /// /// Translates this by the specified amount. @@ -229,16 +196,10 @@ namespace ImageSharp /// /// The used offset this . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Offset(PointF point) - { - this.Offset(point.X, point.Y); - } + public void Offset(PointF point) => this.Offset(point.X, point.Y); /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } + public override int GetHashCode() => this.GetHashCode(this); /// public override string ToString() @@ -252,22 +213,11 @@ namespace ImageSharp } /// - public override bool Equals(object obj) - { - if (obj is PointF) - { - return this.Equals((PointF)obj); - } - - return false; - } + public override bool Equals(object obj) => obj is PointF && this.Equals((PointF)obj); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(PointF other) - { - return this.X.Equals(other.X) && this.Y.Equals(other.Y); - } + public bool Equals(PointF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y); /// /// Returns the hash code for this instance. @@ -278,12 +228,6 @@ namespace ImageSharp /// /// A 32-bit signed integer that is the hash code for this instance. /// - private int GetHashCode(PointF point) - { - unchecked - { - return point.X.GetHashCode() ^ point.Y.GetHashCode(); - } - } + private int GetHashCode(PointF point) => point.X.GetHashCode() ^ point.Y.GetHashCode(); } } \ No newline at end of file diff --git a/src/ImageSharp/Numerics/Size.cs b/src/ImageSharp/Numerics/Size.cs index c46247307..79ee1ddea 100644 --- a/src/ImageSharp/Numerics/Size.cs +++ b/src/ImageSharp/Numerics/Size.cs @@ -87,20 +87,14 @@ namespace ImageSharp /// /// The point [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator SizeF(Size size) - { - return new SizeF(size.Width, size.Height); - } + public static implicit operator SizeF(Size size) => new SizeF(size.Width, size.Height); /// /// Converts the given into a . /// /// The size [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator Point(Size size) - { - return new Point(size.Width, size.Height); - } + public static explicit operator Point(Size size) => new Point(size.Width, size.Height); /// /// Computes the sum of adding two sizes. @@ -111,10 +105,7 @@ namespace ImageSharp /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Size operator +(Size left, Size right) - { - return Add(left, right); - } + public static Size operator +(Size left, Size right) => Add(left, right); /// /// Computes the difference left by subtracting one size from another. @@ -125,10 +116,7 @@ namespace ImageSharp /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Size operator -(Size left, Size right) - { - return Subtract(left, right); - } + public static Size operator -(Size left, Size right) => Subtract(left, right); /// /// Compares two objects for equality. @@ -143,10 +131,7 @@ namespace ImageSharp /// True if the current left is equal to the parameter; otherwise, false. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Size left, Size right) - { - return left.Equals(right); - } + public static bool operator ==(Size left, Size right) => left.Equals(right); /// /// Compares two objects for inequality. @@ -161,10 +146,7 @@ namespace ImageSharp /// True if the current left is unequal to the parameter; otherwise, false. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(Size left, Size right) - { - return !left.Equals(right); - } + public static bool operator !=(Size left, Size right) => !left.Equals(right); /// /// Performs vector addition of two objects. @@ -173,10 +155,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Size Add(Size left, Size right) - { - return new Size(left.Width + right.Width, left.Height + right.Height); - } + public static Size Add(Size left, Size right) => new Size(unchecked(left.Width + right.Width), unchecked(left.Height + right.Height)); /// /// Contracts a by another @@ -185,10 +164,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Size Subtract(Size left, Size right) - { - return new Size(left.Width - right.Width, left.Height - right.Height); - } + public static Size Subtract(Size left, Size right) => new Size(unchecked(left.Width - right.Width), unchecked(left.Height - right.Height)); /// /// Converts a to a by performing a ceiling operation on all the dimensions. @@ -196,10 +172,7 @@ namespace ImageSharp /// The size /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Size Ceiling(SizeF size) - { - return new Size((int)MathF.Ceiling(size.Width), (int)MathF.Ceiling(size.Height)); - } + public static Size Ceiling(SizeF size) => new Size(unchecked((int)MathF.Ceiling(size.Width)), unchecked((int)MathF.Ceiling(size.Height))); /// /// Converts a to a by performing a round operation on all the dimensions. @@ -207,16 +180,18 @@ namespace ImageSharp /// The size /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Size Round(SizeF size) - { - return new Size((int)MathF.Round(size.Width), (int)MathF.Round(size.Height)); - } + public static Size Round(SizeF size) => new Size(unchecked((int)MathF.Round(size.Width)), unchecked((int)MathF.Round(size.Height))); + + /// + /// Converts a to a by performing a round operation on all the dimensions. + /// + /// The size + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Size Truncate(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height)); /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } + public override int GetHashCode() => this.GetHashCode(this); /// public override string ToString() @@ -230,22 +205,11 @@ namespace ImageSharp } /// - public override bool Equals(object obj) - { - if (obj is Size) - { - return this.Equals((Size)obj); - } - - return false; - } + public override bool Equals(object obj) => obj is Size && this.Equals((Size)obj); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(Size other) - { - return this.Width == other.Width && this.Height == other.Height; - } + public bool Equals(Size other) => this.Width == other.Width && this.Height == other.Height; /// /// Returns the hash code for this instance. @@ -256,12 +220,6 @@ namespace ImageSharp /// /// A 32-bit signed integer that is the hash code for this instance. /// - private int GetHashCode(Size size) - { - unchecked - { - return size.Width ^ size.Height; - } - } + private int GetHashCode(Size size) => size.Width ^ size.Height; } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Numerics/SizeF.cs b/src/ImageSharp/Numerics/SizeF.cs index f6b852cfa..78078fd01 100644 --- a/src/ImageSharp/Numerics/SizeF.cs +++ b/src/ImageSharp/Numerics/SizeF.cs @@ -79,20 +79,14 @@ namespace ImageSharp /// The . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator Size(SizeF size) - { - return new Size(unchecked((int)size.Width), unchecked((int)size.Height)); - } + public static explicit operator Size(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height)); /// /// Converts the given into a . /// /// The size [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static explicit operator PointF(SizeF size) - { - return new PointF(size.Width, size.Height); - } + public static explicit operator PointF(SizeF size) => new PointF(size.Width, size.Height); /// /// Computes the sum of adding two sizes. @@ -103,10 +97,7 @@ namespace ImageSharp /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SizeF operator +(SizeF left, SizeF right) - { - return Add(left, right); - } + public static SizeF operator +(SizeF left, SizeF right) => Add(left, right); /// /// Computes the difference left by subtracting one size from another. @@ -117,10 +108,7 @@ namespace ImageSharp /// The /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SizeF operator -(SizeF left, SizeF right) - { - return Subtract(left, right); - } + public static SizeF operator -(SizeF left, SizeF right) => Subtract(left, right); /// /// Compares two objects for equality. @@ -131,10 +119,7 @@ namespace ImageSharp /// True if the current left is equal to the parameter; otherwise, false. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(SizeF left, SizeF right) - { - return left.Equals(right); - } + public static bool operator ==(SizeF left, SizeF right) => left.Equals(right); /// /// Compares two objects for inequality. @@ -145,10 +130,7 @@ namespace ImageSharp /// True if the current left is unequal to the parameter; otherwise, false. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(SizeF left, SizeF right) - { - return !left.Equals(right); - } + public static bool operator !=(SizeF left, SizeF right) => !left.Equals(right); /// /// Performs vector addition of two objects. @@ -157,10 +139,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SizeF Add(SizeF left, SizeF right) - { - return new SizeF(left.Width + right.Width, left.Height + right.Height); - } + public static SizeF Add(SizeF left, SizeF right) => new SizeF(left.Width + right.Width, left.Height + right.Height); /// /// Contracts a by another @@ -169,10 +148,7 @@ namespace ImageSharp /// The size on the right hand of the operand. /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static SizeF Subtract(SizeF left, SizeF right) - { - return new SizeF(left.Width - right.Width, left.Height - right.Height); - } + public static SizeF Subtract(SizeF left, SizeF right) => new SizeF(left.Width - right.Width, left.Height - right.Height); /// public override int GetHashCode() @@ -192,38 +168,12 @@ namespace ImageSharp } /// - public override bool Equals(object obj) - { - if (obj is SizeF) - { - return this.Equals((SizeF)obj); - } - - return false; - } + public override bool Equals(object obj) => obj is SizeF && this.Equals((SizeF)obj); /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Equals(SizeF other) - { - return this.Width.Equals(other.Width) && this.Height.Equals(other.Height); - } + public bool Equals(SizeF other) => this.Width.Equals(other.Width) && this.Height.Equals(other.Height); - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// - private int GetHashCode(SizeF size) - { - unchecked - { - return size.Width.GetHashCode() ^ size.Height.GetHashCode(); - } - } + private int GetHashCode(SizeF size) => size.Width.GetHashCode() ^ size.Height.GetHashCode(); } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs index 23fea94e9..4e4a36a38 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs @@ -52,7 +52,7 @@ namespace ImageSharp.Processing.Processors int startX = sourceRectangle.X; int endX = sourceRectangle.Right; TPixel glowColor = this.GlowColor; - var centre = Rectangle.Center(sourceRectangle).ToVector2(); + Vector2 centre = Rectangle.Center(sourceRectangle); float maxDistance = this.Radius > 0 ? MathF.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; // Align start/end positions. diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs index 4dfa41989..23ba5afe0 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs @@ -58,7 +58,7 @@ namespace ImageSharp.Processing.Processors int startX = sourceRectangle.X; int endX = sourceRectangle.Right; TPixel vignetteColor = this.VignetteColor; - var centre = Rectangle.Center(sourceRectangle).ToVector2(); + Vector2 centre = Rectangle.Center(sourceRectangle); float rX = this.RadiusX > 0 ? MathF.Min(this.RadiusX, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; float rY = this.RadiusY > 0 ? MathF.Min(this.RadiusY, sourceRectangle.Height * .5F) : sourceRectangle.Height * .5F; float maxDistance = MathF.Sqrt((rX * rX) + (rY * rY)); diff --git a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs index 7608d3065..be4929d9a 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs @@ -79,7 +79,7 @@ namespace ImageSharp.Benchmarks int startX = sourceRectangle.X; int endX = sourceRectangle.Right; TPixel glowColor = this.GlowColor; - Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2(); + Vector2 centre = Rectangle.Center(sourceRectangle); float maxDistance = this.Radius > 0 ? MathF.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; // Align start/end positions. From 83c915b504a63cc52556a51971a9746a522e8ea9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 12:39:15 +1000 Subject: [PATCH 35/84] Rectangle and RectangleF --- src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs | 4 +- .../Processors/DrawPathProcessor.cs | 3 +- src/ImageSharp/Numerics/Point.cs | 7 +- src/ImageSharp/Numerics/Rectangle.cs | 440 ++++++++++++------ src/ImageSharp/Numerics/RectangleF.cs | 422 ++++++++++------- .../Numerics/RectangleFTests.cs | 266 +++++++++++ .../Numerics/RectangleTests.cs | 318 +++++++++++-- 7 files changed, 1097 insertions(+), 363 deletions(-) create mode 100644 tests/ImageSharp.Tests/Numerics/RectangleFTests.cs diff --git a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs index 53a3c8c99..a5639e49a 100644 --- a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs +++ b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs @@ -132,7 +132,7 @@ namespace ImageSharp.Drawing.Pens { this.brush = brush.CreateApplicator(sourcePixels, region, options); this.halfWidth = width / 2; - this.RequiredRegion = RectangleF.Outset(region, width); + this.RequiredRegion = RectangleF.Inflate(region, width, width); } public override RectangleF RequiredRegion @@ -185,7 +185,7 @@ namespace ImageSharp.Drawing.Pens this.pattern[i + 1] = this.totalLength; } - this.RequiredRegion = RectangleF.Outset(region, width); + this.RequiredRegion = RectangleF.Inflate(region, width, width); } public override RectangleF RequiredRegion diff --git a/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs b/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs index 860c4c4f0..d40c71f7e 100644 --- a/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs @@ -6,7 +6,6 @@ namespace ImageSharp.Drawing.Processors { using System; - using System.Numerics; using System.Threading.Tasks; using ImageSharp.Memory; @@ -58,7 +57,7 @@ namespace ImageSharp.Drawing.Processors { using (PenApplicator applicator = this.Pen.CreateApplicator(source, this.Path.Bounds, this.Options)) { - Rectangle rect = RectangleF.Ceiling(applicator.RequiredRegion); + var rect = Rectangle.Ceiling(applicator.RequiredRegion); int polyStartY = rect.Y - PaddingFactor; int polyEndY = rect.Bottom + PaddingFactor; diff --git a/src/ImageSharp/Numerics/Point.cs b/src/ImageSharp/Numerics/Point.cs index 4d43a83af..9bff27d2a 100644 --- a/src/ImageSharp/Numerics/Point.cs +++ b/src/ImageSharp/Numerics/Point.cs @@ -213,8 +213,11 @@ namespace ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Offset(int dx, int dy) { - this.X += dx; - this.Y += dy; + unchecked + { + this.X += dx; + this.Y += dy; + } } /// diff --git a/src/ImageSharp/Numerics/Rectangle.cs b/src/ImageSharp/Numerics/Rectangle.cs index b651eff71..d16b22920 100644 --- a/src/ImageSharp/Numerics/Rectangle.cs +++ b/src/ImageSharp/Numerics/Rectangle.cs @@ -8,6 +8,7 @@ namespace ImageSharp using System; using System.ComponentModel; using System.Numerics; + using System.Runtime.CompilerServices; /// /// Stores a set of four integers that represent the location and size of a rectangle. @@ -23,11 +24,6 @@ namespace ImageSharp /// public static readonly Rectangle Empty = default(Rectangle); - /// - /// The backing vector for SIMD support. - /// - private Vector4 backingVector; - /// /// Initializes a new instance of the struct. /// @@ -37,7 +33,10 @@ namespace ImageSharp /// The height of the rectangle. public Rectangle(int x, int y, int width, int height) { - this.backingVector = new Vector4(x, y, width, height); + this.X = x; + this.Y = y; + this.Width = width; + this.Height = height; } /// @@ -51,197 +50,325 @@ namespace ImageSharp /// public Rectangle(Point point, Size size) { - this.backingVector = new Vector4(point.X, point.Y, size.Width, size.Height); + this.X = point.X; + this.Y = point.Y; + this.Width = size.Width; + this.Height = size.Height; } /// - /// Initializes a new instance of the struct. + /// Gets or sets the x-coordinate of this . /// - /// - /// The which specifies the rectangles top left point in a two-dimensional plane. - /// - /// - /// The which specifies the rectangles bottom right point in a two-dimensional plane. - /// - public Rectangle(Point topLeft, Point bottomRight) - { - this.backingVector = new Vector4(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); - } + public int X { get; set; } /// - /// Initializes a new instance of the struct. + /// Gets or sets the y-coordinate of this . /// - /// The vector. - public Rectangle(Vector4 vector) - { - this.backingVector = vector; - } + public int Y { get; set; } /// - /// Gets or sets the x-coordinate of this . + /// Gets or sets the width of this . + /// + public int Width { get; set; } + + /// + /// Gets or sets the height of this . /// - public int X + public int Height { get; set; } + + /// + /// Gets or sets the coordinates of the upper-left corner of the rectangular region represented by this . + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public Point Location { - get - { - return (int)this.backingVector.X; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => new Point(this.X, this.Y); + [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - this.backingVector.X = value; + this.X = value.X; + this.Y = value.Y; } } /// - /// Gets or sets the y-coordinate of this . + /// Gets or sets the size of this . /// - public int Y + [EditorBrowsable(EditorBrowsableState.Never)] + public Size Size { - get - { - return (int)this.backingVector.Y; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => new Size(this.Width, this.Height); + [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - this.backingVector.Y = value; + this.Width = value.Width; + this.Height = value.Height; } } /// - /// Gets or sets the width of this . + /// Gets a value indicating whether this is empty. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool IsEmpty => this.Equals(Empty); + + /// + /// Gets the y-coordinate of the top edge of this . /// - public int Width + public int Top { + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return (int)this.backingVector.Z; + return this.Y; } + } - set + /// + /// Gets the x-coordinate of the right edge of this . + /// + public int Right + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { - this.backingVector.Z = value; + return unchecked(this.X + this.Width); } } /// - /// Gets or sets the height of this . + /// Gets the y-coordinate of the bottom edge of this . /// - public int Height + public int Bottom { + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return (int)this.backingVector.W; + return unchecked(this.Y + this.Height); } + } - set + /// + /// Gets the x-coordinate of the left edge of this . + /// + public int Left + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { - this.backingVector.W = value; + return this.X; } } /// - /// Gets the size of this . + /// Creates a with the coordinates of the specified . /// - public Size Size => new Size(this.Width, this.Height); + /// The rectangle + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator RectangleF(Rectangle rectangle) => new RectangleF(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); /// - /// Gets a value indicating whether this is empty. + /// Creates a with the coordinates of the specified . /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); + /// The rectangle + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Vector4(Rectangle rectangle) => new Vector4(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); /// - /// Gets the y-coordinate of the top edge of this . + /// Compares two objects for equality. /// - public int Top => this.Y; + /// The on the left side of the operand. + /// The on the right side of the operand. + /// + /// True if the current left is equal to the parameter; otherwise, false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(Rectangle left, Rectangle right) => left.Equals(right); /// - /// Gets the x-coordinate of the right edge of this . + /// Compares two objects for inequality. /// - public int Right => this.X + this.Width; + /// The on the left side of the operand. + /// The on the right side of the operand. + /// + /// True if the current left is unequal to the parameter; otherwise, false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(Rectangle left, Rectangle right) => !left.Equals(right); /// - /// Gets the y-coordinate of the bottom edge of this . + /// Creates a new with the specified location and size. + /// The left coordinate of the rectangle + /// The top coordinate of the rectangle + /// The right coordinate of the rectangle + /// The bottom coordinate of the rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + + // ReSharper disable once InconsistentNaming + public static Rectangle FromLTRB(int left, int top, int right, int bottom) => new Rectangle(left, top, unchecked(right - left), unchecked(bottom - top)); + + /// + /// Returns the center point of the given /// - public int Bottom => this.Y + this.Height; + /// The rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Point Center(Rectangle rectangle) => new Point(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); /// - /// Gets the x-coordinate of the left edge of this . + /// Creates a rectangle that represents the intersection between and + /// . If there is no intersection, an empty rectangle is returned. /// - public int Left => this.X; + /// The first rectangle + /// The second rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Rectangle Intersect(Rectangle a, Rectangle b) + { + int x1 = Math.Max(a.X, b.X); + int x2 = Math.Min(a.Right, b.Right); + int y1 = Math.Max(a.Y, b.Y); + int y2 = Math.Min(a.Bottom, b.Bottom); + + if (x2 >= x1 && y2 >= y1) + { + return new Rectangle(x1, y1, x2 - x1, y2 - y1); + } + + return Empty; + } /// - /// Computes the sum of adding two rectangles. + /// Creates a that is inflated by the specified amount. /// - /// The rectangle on the left hand of the operand. - /// The rectangle on the right hand of the operand. - /// - /// The - /// - public static Rectangle operator +(Rectangle left, Rectangle right) + /// The rectangle + /// The amount to inflate the width by + /// The amount to inflate the height by + /// A new + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Rectangle Inflate(Rectangle rectangle, int x, int y) { - return new Rectangle(left.backingVector + right.backingVector); + Rectangle r = rectangle; + r.Inflate(x, y); + return r; } /// - /// Computes the difference left by subtracting one rectangle from another. + /// Converts a to a by performing a ceiling operation on all the coordinates. /// - /// The rectangle on the left hand of the operand. - /// The rectangle on the right hand of the operand. - /// - /// The - /// - public static Rectangle operator -(Rectangle left, Rectangle right) + /// The rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Rectangle Ceiling(RectangleF rectangle) { - return new Rectangle(left.backingVector - right.backingVector); + unchecked + { + return new Rectangle( + (int)MathF.Ceiling(rectangle.X), + (int)MathF.Ceiling(rectangle.Y), + (int)MathF.Ceiling(rectangle.Width), + (int)MathF.Ceiling(rectangle.Height)); + } } /// - /// Compares two objects for equality. + /// Converts a to a by performing a truncate operation on all the coordinates. /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(Rectangle left, Rectangle right) + /// The rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Rectangle Truncate(RectangleF rectangle) { - return left.Equals(right); + unchecked + { + return new Rectangle( + (int)rectangle.X, + (int)rectangle.Y, + (int)rectangle.Width, + (int)rectangle.Height); + } } /// - /// Compares two objects for inequality. + /// Converts a to a by performing a round operation on all the coordinates. /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(Rectangle left, Rectangle right) + /// The rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Rectangle Round(RectangleF rectangle) { - return !left.Equals(right); + unchecked + { + return new Rectangle( + (int)MathF.Round(rectangle.X), + (int)MathF.Round(rectangle.Y), + (int)MathF.Round(rectangle.Width), + (int)MathF.Round(rectangle.Height)); + } } /// - /// Returns the center point of the given + /// Creates a rectangle that represents the union between and . + /// + /// The first rectangle + /// The second rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Rectangle Union(Rectangle a, Rectangle b) + { + int x1 = Math.Min(a.X, b.X); + int x2 = Math.Max(a.Right, b.Right); + int y1 = Math.Min(a.Y, b.Y); + int y2 = Math.Max(a.Bottom, b.Bottom); + + return new Rectangle(x1, y1, x2 - x1, y2 - y1); + } + + /// + /// Creates a Rectangle that represents the intersection between this Rectangle and the . /// /// The rectangle - /// - public static Point Center(Rectangle rectangle) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Intersect(Rectangle rectangle) { - return new Point(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); + Rectangle result = Intersect(rectangle, this); + + this.X = result.X; + this.Y = result.Y; + this.Width = result.Width; + this.Height = result.Height; } + /// + /// Inflates this by the specified amount. + /// + /// The width + /// The height + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Inflate(int width, int height) + { + unchecked + { + this.X -= width; + this.Y -= height; + + this.Width += 2 * width; + this.Height += 2 * height; + } + } + + /// + /// Inflates this by the specified amount. + /// + /// The size + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Inflate(Size size) => this.Inflate(size.Width, size.Height); + /// /// Determines if the specfied point is contained within the rectangular region defined by /// this . @@ -249,33 +376,63 @@ namespace ImageSharp /// The x-coordinate of the given point. /// The y-coordinate of the given point. /// The - public bool Contains(int x, int y) - { - // TODO: SIMD? - return this.X <= x - && x < this.Right - && this.Y <= y - && y < this.Bottom; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(int x, int y) => this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom; + + /// + /// Determines if the specified point is contained within the rectangular region defined by this . + /// + /// The point + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(Point point) => this.Contains(point.X, point.Y); + + /// + /// Determines if the rectangular region represented by is entirely contained + /// within the rectangular region represented by this . + /// + /// The rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(Rectangle rectangle) => + (this.X <= rectangle.X) && (rectangle.Right <= this.Right) && + (this.Y <= rectangle.Y) && (rectangle.Bottom <= this.Bottom); /// /// Determines if the specfied intersects the rectangular region defined by /// this . /// - /// The other Rectange + /// The other Rectange /// The - public bool Intersects(Rectangle rect) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IntersectsWith(Rectangle rectangle) => + (rectangle.X < this.Right) && (this.X < rectangle.Right) && + (rectangle.Y < this.Bottom) && (this.Y < rectangle.Bottom); + + /// + /// Adjusts the location of this rectangle by the specified amount. + /// + /// The point + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Offset(Point point) => this.Offset(point.X, point.Y); + + /// + /// Adjusts the location of this rectangle by the specified amount. + /// + /// The amount to offset the x-coordinate. + /// The amount to offset the y-coordinate. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Offset(int dx, int dy) { - return rect.Left <= this.Right && rect.Right >= this.Left - && - rect.Top <= this.Bottom && rect.Bottom >= this.Top; + unchecked + { + this.X += dx; + this.Y += dy; + } } /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } + public override int GetHashCode() => this.GetHashCode(this); /// public override string ToString() @@ -285,39 +442,26 @@ namespace ImageSharp return "Rectangle [ Empty ]"; } - return - $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; + return $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; } /// - public override bool Equals(object obj) - { - if (obj is Rectangle) - { - return this.Equals((Rectangle)obj); - } - - return false; - } + public override bool Equals(object obj) => obj is Rectangle && this.Equals((Rectangle)obj); /// - public bool Equals(Rectangle other) - { - return this.backingVector.Equals(other.backingVector); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(Rectangle other) => this.X == other.X && this.Y == other.Y && this.Width == other.Width && this.Height == other.Height; - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// private int GetHashCode(Rectangle rectangle) { - return rectangle.backingVector.GetHashCode(); + unchecked + { + int hashCode = rectangle.X; + hashCode = (hashCode * 397) ^ rectangle.Y; + hashCode = (hashCode * 397) ^ rectangle.Width; + hashCode = (hashCode * 397) ^ rectangle.Height; + return hashCode; + } } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Numerics/RectangleF.cs b/src/ImageSharp/Numerics/RectangleF.cs index 2ed57c841..28d887c5d 100644 --- a/src/ImageSharp/Numerics/RectangleF.cs +++ b/src/ImageSharp/Numerics/RectangleF.cs @@ -8,9 +8,10 @@ namespace ImageSharp using System; using System.ComponentModel; using System.Numerics; + using System.Runtime.CompilerServices; /// - /// Stores a set of four integers that represent the location and size of a rectangle. + /// Stores a set of four single precision floating points that represent the location and size of a rectangle. /// /// /// This struct is fully mutable. This is done (against the guidelines) for the sake of performance, @@ -19,15 +20,10 @@ namespace ImageSharp public struct RectangleF : IEquatable { /// - /// Represents a that has X, Y, Width, and Height values set to zero. + /// Represents a that has X, Y, Width, and Height values set to zero. /// public static readonly RectangleF Empty = default(RectangleF); - /// - /// The backing vector for SIMD support. - /// - private Vector4 backingVector; - /// /// Initializes a new instance of the struct. /// @@ -37,221 +33,291 @@ namespace ImageSharp /// The height of the rectangle. public RectangleF(float x, float y, float width, float height) { - this.backingVector = new Vector4(x, y, width, height); + this.X = x; + this.Y = y; + this.Width = width; + this.Height = height; } /// /// Initializes a new instance of the struct. /// - /// The vector. - public RectangleF(Vector4 vector) + /// + /// The which specifies the rectangles point in a two-dimensional plane. + /// + /// + /// The which specifies the rectangles height and width. + /// + public RectangleF(PointF point, SizeF size) { - this.backingVector = vector; + this.X = point.X; + this.Y = point.Y; + this.Width = size.Width; + this.Height = size.Height; } /// /// Gets or sets the x-coordinate of this . /// - public float X + public float X { get; set; } + + /// + /// Gets or sets the y-coordinate of this . + /// + public float Y { get; set; } + + /// + /// Gets or sets the width of this . + /// + public float Width { get; set; } + + /// + /// Gets or sets the height of this . + /// + public float Height { get; set; } + + /// + /// Gets or sets the coordinates of the upper-left corner of the rectangular region represented by this . + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public PointF Location { - get - { - return this.backingVector.X; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => new PointF(this.X, this.Y); + [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - this.backingVector.X = value; + this.X = value.X; + this.Y = value.Y; } } /// - /// Gets or sets the y-coordinate of this . + /// Gets or sets the size of this . /// - public float Y + [EditorBrowsable(EditorBrowsableState.Never)] + public SizeF Size { - get - { - return this.backingVector.Y; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => new SizeF(this.Width, this.Height); + [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - this.backingVector.Y = value; + this.Width = value.Width; + this.Height = value.Height; } } /// - /// Gets or sets the width of this . + /// Gets a value indicating whether this is empty. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public bool IsEmpty => (this.Width <= 0) || (this.Height <= 0); + + /// + /// Gets the y-coordinate of the top edge of this . /// - public float Width + public float Top { + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return this.backingVector.Z; - } - - set - { - this.backingVector.Z = value; + return this.Y; } } /// - /// Gets or sets the height of this . + /// Gets the x-coordinate of the right edge of this . /// - public float Height + public float Right { + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { - return this.backingVector.W; + return this.X + this.Width; } + } - set + /// + /// Gets the y-coordinate of the bottom edge of this . + /// + public float Bottom + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { - this.backingVector.W = value; + return this.Y + this.Height; } } /// - /// Gets a value indicating whether this is empty. + /// Gets the x-coordinate of the left edge of this . /// - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsEmpty => this.Equals(Empty); + public float Left + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return this.X; + } + } /// - /// Gets the y-coordinate of the top edge of this . + /// Creates a with the coordinates of the specified . /// - public float Top => this.Y; + /// The rectangle + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator RectangleF(Vector4 vector) => new RectangleF(vector.X, vector.Y, vector.Z, vector.W); /// - /// Gets the x-coordinate of the right edge of this . + /// Creates a with the coordinates of the specified . /// - public float Right => this.X + this.Width; + /// The rectangle + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator Vector4(RectangleF rectangle) => new Vector4(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); /// - /// Gets the y-coordinate of the bottom edge of this . + /// Creates a with the coordinates of the specified by truncating each coordinate. /// - public float Bottom => this.Y + this.Height; + /// The rectangle + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static explicit operator Rectangle(RectangleF rectangle) => Rectangle.Truncate(rectangle); /// - /// Gets the x-coordinate of the left edge of this . + /// Compares two objects for equality. /// - public float Left => this.X; + /// The on the left side of the operand. + /// The on the right side of the operand. + /// + /// True if the current left is equal to the parameter; otherwise, false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(RectangleF left, RectangleF right) => left.Equals(right); /// - /// Performs an implicit conversion from to . + /// Compares two objects for inequality. /// - /// The d. + /// The on the left side of the operand. + /// The on the right side of the operand. /// - /// The result of the conversion. + /// True if the current left is unequal to the parameter; otherwise, false. /// - public static implicit operator RectangleF(Rectangle d) - { - return new RectangleF(d.Left, d.Top, d.Width, d.Height); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(RectangleF left, RectangleF right) => !left.Equals(right); /// - /// Computes the sum of adding two rectangles. + /// Creates a new with the specified location and size. + /// The left coordinate of the rectangle + /// The top coordinate of the rectangle + /// The right coordinate of the rectangle + /// The bottom coordinate of the rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + + // ReSharper disable once InconsistentNaming + public static RectangleF FromLTRB(float left, float top, float right, float bottom) => new RectangleF(left, top, right - left, bottom - top); + + /// + /// Returns the center point of the given /// - /// The rectangle on the left hand of the operand. - /// The rectangle on the right hand of the operand. - /// - /// The - /// - public static RectangleF operator +(RectangleF left, RectangleF right) - { - return new RectangleF(left.backingVector + right.backingVector); - } + /// The rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static PointF Center(RectangleF rectangle) => new PointF(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); /// - /// Computes the difference left by subtracting one rectangle from another. + /// Creates a rectangle that represents the intersection between and + /// . If there is no intersection, an empty rectangle is returned. /// - /// The rectangle on the left hand of the operand. - /// The rectangle on the right hand of the operand. - /// - /// The - /// - public static RectangleF operator -(RectangleF left, RectangleF right) + /// The first rectangle + /// The second rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RectangleF Intersect(RectangleF a, RectangleF b) { - return new RectangleF(left.backingVector - right.backingVector); + float x1 = MathF.Max(a.X, b.X); + float x2 = MathF.Min(a.Right, b.Right); + float y1 = MathF.Max(a.Y, b.Y); + float y2 = MathF.Min(a.Bottom, b.Bottom); + + if (x2 >= x1 && y2 >= y1) + { + return new RectangleF(x1, y1, x2 - x1, y2 - y1); + } + + return Empty; } /// - /// Compares two objects for equality. + /// Creates a that is inflated by the specified amount. /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is equal to the parameter; otherwise, false. - /// - public static bool operator ==(RectangleF left, RectangleF right) + /// The rectangle + /// The amount to inflate the width by + /// The amount to inflate the height by + /// A new + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RectangleF Inflate(RectangleF rectangle, float x, float y) { - return left.Equals(right); + RectangleF r = rectangle; + r.Inflate(x, y); + return r; } /// - /// Compares two objects for inequality. + /// Creates a rectangle that represents the union between and . /// - /// - /// The on the left side of the operand. - /// - /// - /// The on the right side of the operand. - /// - /// - /// True if the current left is unequal to the parameter; otherwise, false. - /// - public static bool operator !=(RectangleF left, RectangleF right) + /// The first rectangle + /// The second rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static RectangleF Union(RectangleF a, RectangleF b) { - return !left.Equals(right); + float x1 = MathF.Min(a.X, b.X); + float x2 = MathF.Max(a.Right, b.Right); + float y1 = MathF.Min(a.Y, b.Y); + float y2 = MathF.Max(a.Bottom, b.Bottom); + + return new RectangleF(x1, y1, x2 - x1, y2 - y1); } /// - /// Returns the center point of the given + /// Creates a RectangleF that represents the intersection between this RectangleF and the . /// /// The rectangle - /// - public static Vector2 Center(RectangleF rectangle) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Intersect(RectangleF rectangle) { - return new Vector2(rectangle.Left + (rectangle.Width / 2), rectangle.Top + (rectangle.Height / 2)); + RectangleF result = Intersect(rectangle, this); + + this.X = result.X; + this.Y = result.Y; + this.Width = result.Width; + this.Height = result.Height; } /// - /// Rounds the points away from the center this into a - /// by rounding the dimensions to the nerent integer ensuring that the new rectangle is - /// never smaller than the source + /// Inflates this by the specified amount. /// - /// The source area to round out - /// - /// The smallest that the will fit inside. - /// - public static Rectangle Ceiling(RectangleF source) + /// The width + /// The height + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Inflate(float width, float height) { - int y = (int)Math.Floor(source.Y); - int width = (int)Math.Ceiling(source.Width); - int x = (int)Math.Floor(source.X); - int height = (int)Math.Ceiling(source.Height); - return new Rectangle(x, y, width, height); + this.X -= width; + this.Y -= height; + + this.Width += 2 * width; + this.Height += 2 * height; } /// - /// Outsets the specified region. + /// Inflates this by the specified amount. /// - /// The region. - /// The width. - /// - /// The with all dimensions move away from the center by the offset. - /// - public static RectangleF Outset(RectangleF region, float width) - { - float dblWidth = width * 2; - return new RectangleF(region.X - width, region.Y - width, region.Width + dblWidth, region.Height + dblWidth); - } + /// The size + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Inflate(SizeF size) => this.Inflate(size.Width, size.Height); /// /// Determines if the specfied point is contained within the rectangular region defined by @@ -260,75 +326,89 @@ namespace ImageSharp /// The x-coordinate of the given point. /// The y-coordinate of the given point. /// The - public bool Contains(float x, float y) - { - // TODO: SIMD? - return this.X <= x - && x < this.Right - && this.Y <= y - && y < this.Bottom; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(float x, float y) => this.X <= x && x < this.Right && this.Y <= y && y < this.Bottom; + + /// + /// Determines if the specified point is contained within the rectangular region defined by this . + /// + /// The point + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(PointF point) => this.Contains(point.X, point.Y); + + /// + /// Determines if the rectangular region represented by is entirely contained + /// within the rectangular region represented by this . + /// + /// The rectangle + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(RectangleF rectangle) => + (this.X <= rectangle.X) && (rectangle.Right <= this.Right) && + (this.Y <= rectangle.Y) && (rectangle.Bottom <= this.Bottom); /// - /// Determines if the specfied intersects the rectangular region defined by - /// this . + /// Determines if the specfied intersects the rectangular region defined by + /// this . /// - /// The other Rectange + /// The other Rectange /// The - public bool Intersects(RectangleF rect) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool IntersectsWith(RectangleF rectangle) => + (rectangle.X < this.Right) && (this.X < rectangle.Right) && + (rectangle.Y < this.Bottom) && (this.Y < rectangle.Bottom); + + /// + /// Adjusts the location of this rectangle by the specified amount. + /// + /// The point + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Offset(PointF point) => this.Offset(point.X, point.Y); + + /// + /// Adjusts the location of this rectangle by the specified amount. + /// + /// The amount to offset the x-coordinate. + /// The amount to offset the y-coordinate. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Offset(float dx, float dy) { - return rect.Left <= this.Right && rect.Right >= this.Left - && - rect.Top <= this.Bottom && rect.Bottom >= this.Top; + this.X += dx; + this.Y += dy; } /// - public override int GetHashCode() - { - return this.GetHashCode(this); - } + public override int GetHashCode() => this.GetHashCode(this); /// public override string ToString() { if (this.IsEmpty) { - return "Rectangle [ Empty ]"; + return "RectangleF [ Empty ]"; } - return - $"Rectangle [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; + return $"RectangleF [ X={this.X}, Y={this.Y}, Width={this.Width}, Height={this.Height} ]"; } /// - public override bool Equals(object obj) - { - if (obj is RectangleF) - { - return this.Equals((RectangleF)obj); - } - - return false; - } + public override bool Equals(object obj) => obj is RectangleF && this.Equals((RectangleF)obj); /// - public bool Equals(RectangleF other) - { - return this.backingVector.Equals(other.backingVector); - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Equals(RectangleF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y) && this.Width.Equals(other.Width) && this.Height.Equals(other.Height); - /// - /// Returns the hash code for this instance. - /// - /// - /// The instance of to return the hash code for. - /// - /// - /// A 32-bit signed integer that is the hash code for this instance. - /// private int GetHashCode(RectangleF rectangle) { - return rectangle.backingVector.GetHashCode(); + unchecked + { + int hashCode = rectangle.X.GetHashCode(); + hashCode = (hashCode * 397) ^ rectangle.Y.GetHashCode(); + hashCode = (hashCode * 397) ^ rectangle.Width.GetHashCode(); + hashCode = (hashCode * 397) ^ rectangle.Height.GetHashCode(); + return hashCode; + } } } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs b/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs new file mode 100644 index 000000000..e06cf707e --- /dev/null +++ b/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs @@ -0,0 +1,266 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests +{ + using System; + using System.Globalization; + using System.Reflection; + + using Xunit; + + /// + /// Tests the struct. + /// + public class RectangleFTests + { + [Fact] + public void DefaultConstructorTest() + { + Assert.Equal(RectangleF.Empty, new RectangleF()); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] + [InlineData(float.MaxValue, 0, 0, float.MaxValue)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void NonDefaultConstructorTest(float x, float y, float width, float height) + { + var rect1 = new RectangleF(x, y, width, height); + var p = new PointF(x, y); + var s = new SizeF(width, height); + var rect2 = new RectangleF(p, s); + + Assert.Equal(rect1, rect2); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] + [InlineData(float.MaxValue, 0, 0, float.MaxValue)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void FromLTRBTest(float left, float top, float right, float bottom) + { + var expected = new RectangleF(left, top, right - left, bottom - top); + var actual = RectangleF.FromLTRB(left, top, right, bottom); + + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] + [InlineData(float.MaxValue, 0, 0, float.MaxValue)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void DimensionsTest(float x, float y, float width, float height) + { + var rect = new RectangleF(x, y, width, height); + var p = new PointF(x, y); + var s = new SizeF(width, height); + + Assert.Equal(p, rect.Location); + Assert.Equal(s, rect.Size); + Assert.Equal(x, rect.X); + Assert.Equal(y, rect.Y); + Assert.Equal(width, rect.Width); + Assert.Equal(height, rect.Height); + Assert.Equal(x, rect.Left); + Assert.Equal(y, rect.Top); + Assert.Equal(x + width, rect.Right); + Assert.Equal(y + height, rect.Bottom); + } + + [Fact] + public void IsEmptyTest() + { + Assert.True(RectangleF.Empty.IsEmpty); + Assert.True(new RectangleF().IsEmpty); + Assert.True(new RectangleF(1, -2, -10, 10).IsEmpty); + Assert.True(new RectangleF(1, -2, 10, -10).IsEmpty); + Assert.True(new RectangleF(1, -2, 0, 0).IsEmpty); + + Assert.False(new RectangleF(0, 0, 10, 10).IsEmpty); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(float.MaxValue, float.MinValue)] + public static void LocationSetTest(float x, float y) + { + var point = new PointF(x, y); + var rect = new RectangleF(10, 10, 10, 10) { Location = point }; + Assert.Equal(point, rect.Location); + Assert.Equal(point.X, rect.X); + Assert.Equal(point.Y, rect.Y); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(float.MaxValue, float.MinValue)] + public static void SizeSetTest(float x, float y) + { + var size = new SizeF(x, y); + var rect = new RectangleF(10, 10, 10, 10) { Size = size }; + Assert.Equal(size, rect.Size); + Assert.Equal(size.Width, rect.Width); + Assert.Equal(size.Height, rect.Height); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] + [InlineData(float.MaxValue, 0, 0, float.MaxValue)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void EqualityTest(float x, float y, float width, float height) + { + var rect1 = new RectangleF(x, y, width, height); + var rect2 = new RectangleF(width, height, x, y); + + Assert.True(rect1 != rect2); + Assert.False(rect1 == rect2); + Assert.False(rect1.Equals(rect2)); + Assert.False(rect1.Equals((object)rect2)); + } + + [Fact] + public static void EqualityTestNotRectangleF() + { + var rectangle = new RectangleF(0, 0, 0, 0); + Assert.False(rectangle.Equals(null)); + Assert.False(rectangle.Equals(0)); + + // If RectangleF implements IEquatable (e.g. in .NET Core), then classes that are implicitly + // convertible to RectangleF can potentially be equal. + // See https://github.com/dotnet/corefx/issues/5255. + bool expectsImplicitCastToRectangleF = typeof(IEquatable).IsAssignableFrom(rectangle.GetType()); + Assert.Equal(expectsImplicitCastToRectangleF, rectangle.Equals(new Rectangle(0, 0, 0, 0))); + + Assert.False(rectangle.Equals((object)new Rectangle(0, 0, 0, 0))); // No implicit cast + } + + [Fact] + public static void GetHashCodeTest() + { + var rect1 = new RectangleF(10, 10, 10, 10); + var rect2 = new RectangleF(10, 10, 10, 10); + Assert.Equal(rect1.GetHashCode(), rect2.GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new RectangleF(20, 10, 10, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new RectangleF(10, 20, 10, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new RectangleF(10, 10, 20, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new RectangleF(10, 10, 10, 20).GetHashCode()); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void ContainsTest(float x, float y, float width, float height) + { + var rect = new RectangleF(x, y, width, height); + float X = (x + width) / 2; + float Y = (y + height) / 2; + var p = new PointF(X, Y); + var r = new RectangleF(X, Y, width / 2, height / 2); + + Assert.False(rect.Contains(X, Y)); + Assert.False(rect.Contains(p)); + Assert.False(rect.Contains(r)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(float.MaxValue / 2, float.MinValue / 2, float.MinValue / 2, float.MaxValue / 2)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void InflateTest(float x, float y, float width, float height) + { + var rect = new RectangleF(x, y, width, height); + var inflatedRect = new RectangleF(x - width, y - height, width + 2 * width, height + 2 * height); + + rect.Inflate(width, height); + Assert.Equal(inflatedRect, rect); + + var s = new SizeF(x, y); + inflatedRect = RectangleF.Inflate(rect, x, y); + + rect.Inflate(s); + Assert.Equal(inflatedRect, rect); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue, float.MaxValue / 2, float.MinValue / 2)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void IntersectTest(float x, float y, float width, float height) + { + var rect1 = new RectangleF(x, y, width, height); + var rect2 = new RectangleF(y, x, width, height); + var expectedRect = RectangleF.Intersect(rect1, rect2); + rect1.Intersect(rect2); + Assert.Equal(expectedRect, rect1); + Assert.False(rect1.IntersectsWith(expectedRect)); + } + + [Fact] + public static void IntersectIntersectingRectsTest() + { + var rect1 = new RectangleF(0, 0, 5, 5); + var rect2 = new RectangleF(1, 1, 3, 3); + var expected = new RectangleF(1, 1, 3, 3); + + Assert.Equal(expected, RectangleF.Intersect(rect1, rect2)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] + [InlineData(float.MaxValue, 0, 0, float.MaxValue)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void UnionTest(float x, float y, float width, float height) + { + var a = new RectangleF(x, y, width, height); + var b = new RectangleF(width, height, x, y); + + float x1 = Math.Min(a.X, b.X); + float x2 = Math.Max(a.X + a.Width, b.X + b.Width); + float y1 = Math.Min(a.Y, b.Y); + float y2 = Math.Max(a.Y + a.Height, b.Y + b.Height); + + var expectedRectangle = new RectangleF(x1, y1, x2 - x1, y2 - y1); + + Assert.Equal(expectedRectangle, RectangleF.Union(a, b)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue)] + [InlineData(float.MaxValue, 0, 0, float.MaxValue)] + [InlineData(0, float.MinValue, float.MaxValue, 0)] + public void OffsetTest(float x, float y, float width, float height) + { + var r1 = new RectangleF(x, y, width, height); + var expectedRect = new RectangleF(x + width, y + height, width, height); + var p = new PointF(width, height); + + r1.Offset(p); + Assert.Equal(expectedRect, r1); + + expectedRect.Offset(p); + r1.Offset(width, height); + Assert.Equal(expectedRect, r1); + } + + [Fact] + public void ToStringTest() + { + var r = new RectangleF(5, -5, 0, 1); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, "RectangleF [ X={0}, Y={1}, Width={2}, Height={3} ]", r.X, r.Y, r.Width, r.Height), r.ToString()); + } + + [Fact] + public void ToStringTestEmpty() + { + var r = new RectangleF(0, 0, 0, 0); + Assert.Equal("RectangleF [ Empty ]", r.ToString()); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Numerics/RectangleTests.cs b/tests/ImageSharp.Tests/Numerics/RectangleTests.cs index 2f9ad3d37..1ef03f0c6 100644 --- a/tests/ImageSharp.Tests/Numerics/RectangleTests.cs +++ b/tests/ImageSharp.Tests/Numerics/RectangleTests.cs @@ -5,6 +5,9 @@ namespace ImageSharp.Tests { + using System; + using System.Globalization; + using Xunit; /// @@ -12,55 +15,294 @@ namespace ImageSharp.Tests /// public class RectangleTests { - /// - /// Tests the equality operators for equality. - /// [Fact] - public void AreEqual() + public void DefaultConstructorTest() + { + Assert.Equal(Rectangle.Empty, new Rectangle()); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(0, 0, 0, 0)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + public void NonDefaultConstructorTest(int x, int y, int width, int height) + { + var rect1 = new Rectangle(x, y, width, height); + var rect2 = new Rectangle(new Point(x, y), new Size(width, height)); + + Assert.Equal(rect1, rect2); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(0, 0, 0, 0)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + public void FromLTRBTest(int left, int top, int right, int bottom) { - Rectangle first = new Rectangle(1, 1, 100, 100); - Rectangle second = new Rectangle(1, 1, 100, 100); + var rect1 = new Rectangle(left, top, unchecked(right - left), unchecked(bottom - top)); + var rect2 = Rectangle.FromLTRB(left, top, right, bottom); - Assert.Equal(first, second); + Assert.Equal(rect1, rect2); } - /// - /// Tests the equality operators for inequality. - /// [Fact] - public void AreNotEqual() + public void EmptyTest() + { + Assert.True(Rectangle.Empty.IsEmpty); + Assert.True(new Rectangle(0, 0, 0, 0).IsEmpty); + Assert.True(new Rectangle().IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + public void NonEmptyTest(int x, int y, int width, int height) + { + Assert.False(new Rectangle(x, y, width, height).IsEmpty); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(0, 0, 0, 0)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + [InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] + public void DimensionsTest(int x, int y, int width, int height) + { + var rect = new Rectangle(x, y, width, height); + Assert.Equal(new Point(x, y), rect.Location); + Assert.Equal(new Size(width, height), rect.Size); + + Assert.Equal(x, rect.X); + Assert.Equal(y, rect.Y); + Assert.Equal(width, rect.Width); + Assert.Equal(height, rect.Height); + Assert.Equal(x, rect.Left); + Assert.Equal(y, rect.Top); + Assert.Equal(unchecked(x + width), rect.Right); + Assert.Equal(unchecked(y + height), rect.Bottom); + + var p = new Point(width, height); + var s = new Size(x, y); + rect.Location = p; + rect.Size = s; + + Assert.Equal(p, rect.Location); + Assert.Equal(s, rect.Size); + + Assert.Equal(width, rect.X); + Assert.Equal(height, rect.Y); + Assert.Equal(x, rect.Width); + Assert.Equal(y, rect.Height); + Assert.Equal(width, rect.Left); + Assert.Equal(height, rect.Top); + Assert.Equal(unchecked(x + width), rect.Right); + Assert.Equal(unchecked(y + height), rect.Bottom); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(int.MaxValue, int.MinValue)] + public static void LocationSetTest(int x, int y) + { + var point = new Point(x, y); + var rect = new Rectangle(10, 10, 10, 10) { Location = point }; + Assert.Equal(point, rect.Location); + Assert.Equal(point.X, rect.X); + Assert.Equal(point.Y, rect.Y); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(int.MaxValue, int.MinValue)] + public static void SizeSetTest(int x, int y) { - Rectangle first = new Rectangle(1, 1, 0, 100); - Rectangle second = new Rectangle(1, 1, 100, 100); + var size = new Size(x, y); + var rect = new Rectangle(10, 10, 10, 10) { Size = size }; + Assert.Equal(size, rect.Size); + Assert.Equal(size.Width, rect.Width); + Assert.Equal(size.Height, rect.Height); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MaxValue, int.MinValue)] + [InlineData(int.MaxValue, 0, int.MinValue, 0)] + [InlineData(0, int.MinValue, 0, int.MaxValue)] + [InlineData(int.MinValue, int.MaxValue, int.MinValue, int.MaxValue)] + public void EqualityTest(int x, int y, int width, int height) + { + var rect1 = new Rectangle(x, y, width, height); + var rect2 = new Rectangle(width / 2, height / 2, x, y); - Assert.NotEqual(first, second); + Assert.True(rect1 != rect2); + Assert.False(rect1 == rect2); + Assert.False(rect1.Equals(rect2)); + Assert.False(rect1.Equals((object)rect2)); } - /// - /// Tests whether the rectangle constructors correctly assign properties. - /// [Fact] - public void ConstructorAssignsProperties() - { - Rectangle first = new Rectangle(1, 1, 50, 100); - Assert.Equal(1, first.X); - Assert.Equal(1, first.Y); - Assert.Equal(50, first.Width); - Assert.Equal(100, first.Height); - Assert.Equal(1, first.Top); - Assert.Equal(51, first.Right); - Assert.Equal(101, first.Bottom); - Assert.Equal(1, first.Left); - - Rectangle second = new Rectangle(new Point(1, 1), new Size(50, 100)); - Assert.Equal(1, second.X); - Assert.Equal(1, second.Y); - Assert.Equal(50, second.Width); - Assert.Equal(100, second.Height); - Assert.Equal(1, second.Top); - Assert.Equal(51, second.Right); - Assert.Equal(101, second.Bottom); - Assert.Equal(1, second.Left); + public static void EqualityTestNotRectangle() + { + var rectangle = new Rectangle(0, 0, 0, 0); + Assert.False(rectangle.Equals(null)); + Assert.False(rectangle.Equals(0)); + Assert.False(rectangle.Equals(new RectangleF(0, 0, 0, 0))); + } + + [Fact] + public static void GetHashCodeTest() + { + var rect1 = new Rectangle(10, 10, 10, 10); + var rect2 = new Rectangle(10, 10, 10, 10); + Assert.Equal(rect1.GetHashCode(), rect2.GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new Rectangle(20, 10, 10, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new Rectangle(10, 20, 10, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new Rectangle(10, 10, 20, 10).GetHashCode()); + Assert.NotEqual(rect1.GetHashCode(), new Rectangle(10, 10, 10, 20).GetHashCode()); + } + + [Theory] + [InlineData(float.MaxValue, float.MinValue, float.MaxValue, float.MinValue)] + [InlineData(float.MinValue, float.MaxValue, float.MinValue, float.MaxValue)] + [InlineData(0, 0, 0, 0)] + public void RectangleFConversionTest(float x, float y, float width, float height) + { + var rect = new RectangleF(x, y, width, height); + Rectangle rCeiling, rTruncate, rRound; + + unchecked + { + rCeiling = new Rectangle((int)Math.Ceiling(x), (int)Math.Ceiling(y), + (int)Math.Ceiling(width), (int)Math.Ceiling(height)); + rTruncate = new Rectangle((int)x, (int)y, (int)width, (int)height); + rRound = new Rectangle((int)Math.Round(x), (int)Math.Round(y), + (int)Math.Round(width), (int)Math.Round(height)); + } + + Assert.Equal(rCeiling, Rectangle.Ceiling(rect)); + Assert.Equal(rTruncate, Rectangle.Truncate(rect)); + Assert.Equal(rRound, Rectangle.Round(rect)); + } + + [Theory] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void ContainsTest(int x, int y, int width, int height) + { + var rect = new Rectangle(unchecked(2 * x - width), unchecked(2 * y - height), width, height); + var p = new Point(x, y); + var r = new Rectangle(x, y, width / 2, height / 2); + + Assert.False(rect.Contains(x, y)); + Assert.False(rect.Contains(p)); + Assert.False(rect.Contains(r)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void InflateTest(int x, int y, int width, int height) + { + Rectangle inflatedRect, rect = new Rectangle(x, y, width, height); + unchecked + { + inflatedRect = new Rectangle(x - width, y - height, width + 2 * width, height + 2 * height); + } + + Assert.Equal(inflatedRect, Rectangle.Inflate(rect, width, height)); + + rect.Inflate(width, height); + Assert.Equal(inflatedRect, rect); + + var s = new Size(x, y); + unchecked + { + inflatedRect = new Rectangle(rect.X - x, rect.Y - y, rect.Width + 2 * x, rect.Height + 2 * y); + } + + rect.Inflate(s); + Assert.Equal(inflatedRect, rect); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void IntersectTest(int x, int y, int width, int height) + { + var rect = new Rectangle(x, y, width, height); + var expectedRect = Rectangle.Intersect(rect, rect); + rect.Intersect(rect); + Assert.Equal(expectedRect, rect); + Assert.False(rect.IntersectsWith(expectedRect)); + } + + [Fact] + public static void IntersectIntersectingRectsTest() + { + var rect1 = new Rectangle(0, 0, 5, 5); + var rect2 = new Rectangle(1, 1, 3, 3); + var expected = new Rectangle(1, 1, 3, 3); + + Assert.Equal(expected, Rectangle.Intersect(rect1, rect2)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(int.MaxValue, 0, 0, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void UnionTest(int x, int y, int width, int height) + { + var a = new Rectangle(x, y, width, height); + var b = new Rectangle(width, height, x, y); + + int x1 = Math.Min(a.X, b.X); + int x2 = Math.Max(a.X + a.Width, b.X + b.Width); + int y1 = Math.Min(a.Y, b.Y); + int y2 = Math.Max(a.Y + a.Height, b.Y + b.Height); + + var expectedRectangle = new Rectangle(x1, y1, x2 - x1, y2 - y1); + + Assert.Equal(expectedRectangle, Rectangle.Union(a, b)); + } + + [Theory] + [InlineData(0, 0, 0, 0)] + [InlineData(int.MaxValue, int.MinValue, int.MinValue, int.MaxValue)] + [InlineData(int.MaxValue, 0, 0, int.MaxValue)] + [InlineData(0, int.MinValue, int.MaxValue, 0)] + public void OffsetTest(int x, int y, int width, int height) + { + var r1 = new Rectangle(x, y, width, height); + var expectedRect = new Rectangle(x + width, y + height, width, height); + var p = new Point(width, height); + + r1.Offset(p); + Assert.Equal(expectedRect, r1); + + expectedRect.Offset(p); + r1.Offset(width, height); + Assert.Equal(expectedRect, r1); + } + + [Fact] + public void ToStringTest() + { + var r = new Rectangle(5, -5, 0, 1); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, "Rectangle [ X={0}, Y={1}, Width={2}, Height={3} ]", r.X, r.Y, r.Width, r.Height), r.ToString()); + } + + [Fact] + public void ToStringTestEmpty() + { + var r = new Rectangle(0, 0, 0, 0); + Assert.Equal("Rectangle [ Empty ]", r.ToString()); } } } \ No newline at end of file From a9bcb3ae819ff9407578cc5ae60fbc2b84402722 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 13:02:03 +1000 Subject: [PATCH 36/84] Fix RectangleF empty test --- tests/ImageSharp.Tests/Numerics/RectangleFTests.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs b/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs index e06cf707e..b20b660dd 100644 --- a/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs +++ b/tests/ImageSharp.Tests/Numerics/RectangleFTests.cs @@ -252,14 +252,15 @@ namespace ImageSharp.Tests [Fact] public void ToStringTest() { - var r = new RectangleF(5, -5, 0, 1); + var r = new RectangleF(5, 5.1F, 1.3F, 1); Assert.Equal(string.Format(CultureInfo.CurrentCulture, "RectangleF [ X={0}, Y={1}, Width={2}, Height={3} ]", r.X, r.Y, r.Width, r.Height), r.ToString()); } - [Fact] - public void ToStringTestEmpty() + [InlineData(0, 0, 0, 0)] + [InlineData(5, -5, 0.2, -1.3)] + public void ToStringTestEmpty(float x, float y, float width, float height) { - var r = new RectangleF(0, 0, 0, 0); + var r = new RectangleF(x, y, width, height); Assert.Equal("RectangleF [ Empty ]", r.ToString()); } } From 7bbc398d6325623a3d03b761ca15d494d6ce2cc9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 14:07:22 +1000 Subject: [PATCH 37/84] Add Skew/Rotate tests --- .../ImageSharp.Tests/Numerics/PointFTests.cs | 22 ++++++++++++++++++ tests/ImageSharp.Tests/Numerics/PointTests.cs | 23 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/tests/ImageSharp.Tests/Numerics/PointFTests.cs b/tests/ImageSharp.Tests/Numerics/PointFTests.cs index 33de60ca7..3b5a72a14 100644 --- a/tests/ImageSharp.Tests/Numerics/PointFTests.cs +++ b/tests/ImageSharp.Tests/Numerics/PointFTests.cs @@ -7,6 +7,7 @@ namespace ImageSharp.Tests.Numerics { using System; using System.Globalization; + using System.Numerics; using System.Reflection; using Xunit; @@ -101,6 +102,27 @@ namespace ImageSharp.Tests.Numerics Assert.Equal(subExpected, PointF.Subtract(p, s)); } + [Fact] + public void RotateTest() + { + var p = new PointF(13, 17); + Matrix3x2 matrix = Matrix3x2Extensions.CreateRotation(45, PointF.Empty); + + var pout = PointF.Rotate(p, matrix); + + Assert.Equal(new PointF(-2.82842732F, 21.2132034F), pout); + } + + [Fact] + public void SkewTest() + { + var p = new PointF(13, 17); + Matrix3x2 matrix = Matrix3x2Extensions.CreateSkew(45, 45, PointF.Empty); + + var pout = PointF.Skew(p, matrix); + Assert.Equal(new PointF(30, 30), pout); + } + [Theory] [InlineData(float.MaxValue, float.MinValue)] [InlineData(float.MinValue, float.MaxValue)] diff --git a/tests/ImageSharp.Tests/Numerics/PointTests.cs b/tests/ImageSharp.Tests/Numerics/PointTests.cs index 8eb36b6e8..9f7abe067 100644 --- a/tests/ImageSharp.Tests/Numerics/PointTests.cs +++ b/tests/ImageSharp.Tests/Numerics/PointTests.cs @@ -6,6 +6,8 @@ namespace ImageSharp.Tests { using System.Globalization; + using System.Numerics; + using Xunit; public class PointTests @@ -155,6 +157,27 @@ namespace ImageSharp.Tests Assert.Equal(p1, p2); } + [Fact] + public void RotateTest() + { + var p = new Point(13, 17); + Matrix3x2 matrix = Matrix3x2Extensions.CreateRotation(45, Point.Empty); + + var pout = Point.Rotate(p, matrix); + + Assert.Equal(new Point(-3, 21), pout); + } + + [Fact] + public void SkewTest() + { + var p = new Point(13, 17); + Matrix3x2 matrix = Matrix3x2Extensions.CreateSkew(45, 45, Point.Empty); + + var pout = Point.Skew(p, matrix); + Assert.Equal(new Point(30, 30), pout); + } + [Theory] [InlineData(int.MaxValue, int.MinValue)] [InlineData(int.MinValue, int.MinValue)] From 0dcbf0af2efb7e7991335491a816fd92062564ec Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 18:20:44 +1000 Subject: [PATCH 38/84] BinaryThresholdTests as template --- src/ImageSharp/Image/ImageBase{TPixel}.cs | 2 +- .../Image/ImageProcessingExtensions.cs | 2 +- src/ImageSharp/Image/Image{TPixel}.cs | 2 +- .../Processing/ColorMatrix/BlackWhite.cs | 2 +- .../Processing/ColorMatrix/ColorBlindness.cs | 2 +- .../Processing/ColorMatrix/Grayscale.cs | 2 +- src/ImageSharp/Processing/ColorMatrix/Hue.cs | 2 +- .../Processing/ColorMatrix/Kodachrome.cs | 2 +- .../Processing/ColorMatrix/Lomograph.cs | 2 +- .../Processing/ColorMatrix/Polaroid.cs | 2 +- .../Processing/ColorMatrix/Saturation.cs | 2 +- .../Processing/ColorMatrix/Sepia.cs | 2 +- .../Processing/Convolution/DetectEdges.cs | 2 +- .../Processing/Convolution/GaussianBlur.cs | 2 +- .../Processing/Convolution/GaussianSharpen.cs | 2 +- .../Processing/Transforms/AutoOrient.cs | 2 +- src/ImageSharp/Processing/Transforms/Flip.cs | 2 +- src/ImageSharp/Processing/Transforms/Pad.cs | 2 +- .../Processing/Transforms/Resize.cs | 2 +- .../Processing/Transforms/Rotate.cs | 2 +- .../Processing/Transforms/RotateFlip.cs | 2 +- .../Samplers/DetectEdges.cs | 2 +- .../Drawing/Paths/Extensions.cs | 2 +- .../Drawing/Paths/ProcessorWatchingImage.cs | 2 +- .../Drawing/Paths/ShapePathTests.cs | 2 +- .../Drawing/Paths/ShapeRegionTests.cs | 2 +- .../Drawing/Text/OutputText.cs | 2 +- tests/ImageSharp.Tests/FileTestBase.cs | 36 +++++++ .../Formats/Png/PngDecoderTests.cs | 2 +- .../Binarization/BinaryThresholdTest.cs | 47 ++++++++++ .../Binarization}/DitherTest.cs | 0 .../Processors/Filters/AutoOrientTests.cs | 2 +- .../Processors/Filters/BinaryThresholdTest.cs | 57 ------------ .../Processors/Filters/ColorBlindnessTest.cs | 2 +- .../Processors/Filters/DetectEdgesTest.cs | 2 +- .../Processors/Filters/FlipTests.cs | 2 +- .../Processors/Filters/ResizeTests.cs | 2 +- .../Processors/Filters/RotateFlipTest.cs | 2 +- .../Processors/Filters/RotateTest.cs | 2 +- tests/ImageSharp.Tests/TestImages.cs | 19 +++- .../Attributes/ImageDataAttributeBase.cs | 93 ++++++++++++------- .../Attributes/WithBlankImageAttribute.cs | 1 + .../Attributes/WithFileCollectionAttribute.cs | 35 +++++-- .../ImageProviders/FileProvider.cs | 5 +- .../TestUtilities/TestImageExtensions.cs | 27 ++++-- .../TestUtilities/TestUtilityExtensions.cs | 5 + 46 files changed, 243 insertions(+), 152 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs rename tests/ImageSharp.Tests/{Processors/Filters => Processing/Binarization}/DitherTest.cs (100%) delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/BinaryThresholdTest.cs diff --git a/src/ImageSharp/Image/ImageBase{TPixel}.cs b/src/ImageSharp/Image/ImageBase{TPixel}.cs index 508c73eb2..647d60075 100644 --- a/src/ImageSharp/Image/ImageBase{TPixel}.cs +++ b/src/ImageSharp/Image/ImageBase{TPixel}.cs @@ -11,7 +11,7 @@ namespace ImageSharp using ImageSharp.Memory; using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; /// /// The base class of all images. Encapsulates the basic properties and methods required to manipulate diff --git a/src/ImageSharp/Image/ImageProcessingExtensions.cs b/src/ImageSharp/Image/ImageProcessingExtensions.cs index c9577ac15..8eed103d1 100644 --- a/src/ImageSharp/Image/ImageProcessingExtensions.cs +++ b/src/ImageSharp/Image/ImageProcessingExtensions.cs @@ -7,7 +7,7 @@ namespace ImageSharp { using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; /// /// Extension methods for the type. diff --git a/src/ImageSharp/Image/Image{TPixel}.cs b/src/ImageSharp/Image/Image{TPixel}.cs index 092706e41..059ccb9a0 100644 --- a/src/ImageSharp/Image/Image{TPixel}.cs +++ b/src/ImageSharp/Image/Image{TPixel}.cs @@ -15,7 +15,7 @@ namespace ImageSharp using Formats; using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; /// /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. diff --git a/src/ImageSharp/Processing/ColorMatrix/BlackWhite.cs b/src/ImageSharp/Processing/ColorMatrix/BlackWhite.cs index 76977455a..de543f2cd 100644 --- a/src/ImageSharp/Processing/ColorMatrix/BlackWhite.cs +++ b/src/ImageSharp/Processing/ColorMatrix/BlackWhite.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/ColorMatrix/ColorBlindness.cs b/src/ImageSharp/Processing/ColorMatrix/ColorBlindness.cs index d012d6fe2..c48a86293 100644 --- a/src/ImageSharp/Processing/ColorMatrix/ColorBlindness.cs +++ b/src/ImageSharp/Processing/ColorMatrix/ColorBlindness.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/ColorMatrix/Grayscale.cs b/src/ImageSharp/Processing/ColorMatrix/Grayscale.cs index 8700b63e8..89bc2a947 100644 --- a/src/ImageSharp/Processing/ColorMatrix/Grayscale.cs +++ b/src/ImageSharp/Processing/ColorMatrix/Grayscale.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/ColorMatrix/Hue.cs b/src/ImageSharp/Processing/ColorMatrix/Hue.cs index 8dbc55530..bcaf68d9a 100644 --- a/src/ImageSharp/Processing/ColorMatrix/Hue.cs +++ b/src/ImageSharp/Processing/ColorMatrix/Hue.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/ColorMatrix/Kodachrome.cs b/src/ImageSharp/Processing/ColorMatrix/Kodachrome.cs index 13a71a71e..a302bb2e9 100644 --- a/src/ImageSharp/Processing/ColorMatrix/Kodachrome.cs +++ b/src/ImageSharp/Processing/ColorMatrix/Kodachrome.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/ColorMatrix/Lomograph.cs b/src/ImageSharp/Processing/ColorMatrix/Lomograph.cs index 937dca9ba..cbfeb7d05 100644 --- a/src/ImageSharp/Processing/ColorMatrix/Lomograph.cs +++ b/src/ImageSharp/Processing/ColorMatrix/Lomograph.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/ColorMatrix/Polaroid.cs b/src/ImageSharp/Processing/ColorMatrix/Polaroid.cs index f1a573c05..ac9f7391f 100644 --- a/src/ImageSharp/Processing/ColorMatrix/Polaroid.cs +++ b/src/ImageSharp/Processing/ColorMatrix/Polaroid.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/ColorMatrix/Saturation.cs b/src/ImageSharp/Processing/ColorMatrix/Saturation.cs index c41f304b4..ffe336c62 100644 --- a/src/ImageSharp/Processing/ColorMatrix/Saturation.cs +++ b/src/ImageSharp/Processing/ColorMatrix/Saturation.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/ColorMatrix/Sepia.cs b/src/ImageSharp/Processing/ColorMatrix/Sepia.cs index 39eca4e8e..8488dcfe5 100644 --- a/src/ImageSharp/Processing/ColorMatrix/Sepia.cs +++ b/src/ImageSharp/Processing/ColorMatrix/Sepia.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Convolution/DetectEdges.cs b/src/ImageSharp/Processing/Convolution/DetectEdges.cs index 3aa1d0b51..368688f62 100644 --- a/src/ImageSharp/Processing/Convolution/DetectEdges.cs +++ b/src/ImageSharp/Processing/Convolution/DetectEdges.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Convolution/GaussianBlur.cs b/src/ImageSharp/Processing/Convolution/GaussianBlur.cs index 72abec6df..0b8c5383c 100644 --- a/src/ImageSharp/Processing/Convolution/GaussianBlur.cs +++ b/src/ImageSharp/Processing/Convolution/GaussianBlur.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Convolution/GaussianSharpen.cs b/src/ImageSharp/Processing/Convolution/GaussianSharpen.cs index 2ed99ea26..1a5d3c2df 100644 --- a/src/ImageSharp/Processing/Convolution/GaussianSharpen.cs +++ b/src/ImageSharp/Processing/Convolution/GaussianSharpen.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Transforms/AutoOrient.cs b/src/ImageSharp/Processing/Transforms/AutoOrient.cs index f9d3a60aa..b892db41a 100644 --- a/src/ImageSharp/Processing/Transforms/AutoOrient.cs +++ b/src/ImageSharp/Processing/Transforms/AutoOrient.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Transforms/Flip.cs b/src/ImageSharp/Processing/Transforms/Flip.cs index 342b4dd46..1c8baebf1 100644 --- a/src/ImageSharp/Processing/Transforms/Flip.cs +++ b/src/ImageSharp/Processing/Transforms/Flip.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Transforms/Pad.cs b/src/ImageSharp/Processing/Transforms/Pad.cs index 42851e205..4bded0772 100644 --- a/src/ImageSharp/Processing/Transforms/Pad.cs +++ b/src/ImageSharp/Processing/Transforms/Pad.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Transforms/Resize.cs b/src/ImageSharp/Processing/Transforms/Resize.cs index 543b98297..0ed682648 100644 --- a/src/ImageSharp/Processing/Transforms/Resize.cs +++ b/src/ImageSharp/Processing/Transforms/Resize.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Transforms/Rotate.cs b/src/ImageSharp/Processing/Transforms/Rotate.cs index de9dbdc3b..af7c06a27 100644 --- a/src/ImageSharp/Processing/Transforms/Rotate.cs +++ b/src/ImageSharp/Processing/Transforms/Rotate.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Processing.Processors; /// diff --git a/src/ImageSharp/Processing/Transforms/RotateFlip.cs b/src/ImageSharp/Processing/Transforms/RotateFlip.cs index 460d004cb..805deb8d1 100644 --- a/src/ImageSharp/Processing/Transforms/RotateFlip.cs +++ b/src/ImageSharp/Processing/Transforms/RotateFlip.cs @@ -9,7 +9,7 @@ namespace ImageSharp using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; /// /// Extension methods for the type. diff --git a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs b/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs index d4920ff08..e77716ec8 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs @@ -9,7 +9,7 @@ namespace ImageSharp.Benchmarks using BenchmarkDotNet.Attributes; - using Processing; + using ImageSharp.Processing; using CoreImage = ImageSharp.Image; diff --git a/tests/ImageSharp.Tests/Drawing/Paths/Extensions.cs b/tests/ImageSharp.Tests/Drawing/Paths/Extensions.cs index a18dd90bc..24f2a6bd8 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/Extensions.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/Extensions.cs @@ -5,7 +5,7 @@ namespace ImageSharp.Tests.Drawing.Paths using System.IO; using ImageSharp; using ImageSharp.Drawing.Brushes; - using Processing; + using ImageSharp.Processing; using System.Collections.Generic; using Xunit; using ImageSharp.Drawing; diff --git a/tests/ImageSharp.Tests/Drawing/Paths/ProcessorWatchingImage.cs b/tests/ImageSharp.Tests/Drawing/Paths/ProcessorWatchingImage.cs index c1d34a112..039216078 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/ProcessorWatchingImage.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/ProcessorWatchingImage.cs @@ -4,7 +4,7 @@ namespace ImageSharp.Tests.Drawing.Paths using System; using System.IO; using ImageSharp; - using Processing; + using ImageSharp.Processing; using System.Collections.Generic; using ImageSharp.PixelFormats; diff --git a/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs index 494e2a672..d26745a27 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs @@ -5,7 +5,7 @@ namespace ImageSharp.Tests.Drawing.Paths using System.IO; using ImageSharp; using ImageSharp.Drawing.Brushes; - using Processing; + using ImageSharp.Processing; using System.Collections.Generic; using Xunit; using ImageSharp.Drawing; diff --git a/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs index 78c349233..1f2e92c16 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs @@ -5,7 +5,7 @@ namespace ImageSharp.Tests.Drawing.Paths using System.IO; using ImageSharp; using ImageSharp.Drawing.Brushes; - using Processing; + using ImageSharp.Processing; using System.Collections.Generic; using Xunit; using ImageSharp.Drawing; diff --git a/tests/ImageSharp.Tests/Drawing/Text/OutputText.cs b/tests/ImageSharp.Tests/Drawing/Text/OutputText.cs index bb9cd264e..21646b03f 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/OutputText.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/OutputText.cs @@ -5,7 +5,7 @@ namespace ImageSharp.Tests.Drawing.Text using System.IO; using ImageSharp; using ImageSharp.Drawing.Brushes; - using Processing; + using ImageSharp.Processing; using System.Collections.Generic; using Xunit; using ImageSharp.Drawing; diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs index 12c7d5154..4316efdd8 100644 --- a/tests/ImageSharp.Tests/FileTestBase.cs +++ b/tests/ImageSharp.Tests/FileTestBase.cs @@ -12,6 +12,42 @@ namespace ImageSharp.Tests /// public abstract class FileTestBase : TestBase { + /// + /// A collection of all the bmp test images + /// + public static IEnumerable AllBmpFiles => TestImages.Bmp.All; + + /// + /// A collection of all the jpeg test images + /// + public static IEnumerable AllJpegFiles => TestImages.Jpeg.All; + + /// + /// A collection of all the png test images + /// + public static IEnumerable AllPngFiles => TestImages.Png.All; + + /// + /// A collection of all the gif test images + /// + public static IEnumerable AllGifFiles => TestImages.Gif.All; + + /// + /// The standard pixel formats enumerations + /// + public const PixelTypes StandardPixelTypes = PixelTypes.StandardImageClass | PixelTypes.Rgba32 | PixelTypes.Argb32; + + public static class Extensions + { + public const string Bmp = "bmp"; + + public const string Jpeg = "jpg"; + + public const string Png = "png"; + + public const string Gif = "gif"; + } + /// /// The collection of image files to test against. /// diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index cf5c1cfa9..3d3f5b006 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -18,7 +18,7 @@ namespace ImageSharp.Tests public static readonly string[] TestFiles = { TestImages.Png.Splash, TestImages.Png.Indexed, TestImages.Png.Interlaced, TestImages.Png.FilterVar, - TestImages.Png.ChunkLength1, TestImages.Png.ChunkLength2 + TestImages.Png.Bad.ChunkLength1, TestImages.Png.Bad.ChunkLength2 }; [Theory] diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs new file mode 100644 index 000000000..f3dcbe1cd --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs @@ -0,0 +1,47 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Binarization +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class BinaryThresholdTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes, .75F)] + public void ImageShouldApplyBinaryThresholdFilter(TestImageProvider provider, float value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.BinaryThreshold(value) + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes, .75F)] + public void ImageShouldApplyBinaryThresholdInBox(TestImageProvider provider, float value) + where TPixel : struct, IPixel + { + + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.BinaryThreshold(value, bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs similarity index 100% rename from tests/ImageSharp.Tests/Processors/Filters/DitherTest.cs rename to tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs diff --git a/tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs index 470e7150b..d31a7468f 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs @@ -9,7 +9,7 @@ namespace ImageSharp.Tests using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Xunit; public class AutoOrientTests : FileTestBase diff --git a/tests/ImageSharp.Tests/Processors/Filters/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processors/Filters/BinaryThresholdTest.cs deleted file mode 100644 index 4e5e8a82e..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/BinaryThresholdTest.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class BinaryThresholdTest : FileTestBase - { - public static readonly TheoryData BinaryThresholdValues - = new TheoryData - { - .25f , - .75f , - }; - - [Theory] - [MemberData(nameof(BinaryThresholdValues))] - public void ImageShouldApplyBinaryThresholdFilter(float value) - { - string path = this.CreateOutputDirectory("BinaryThreshold"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.BinaryThreshold(value).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(BinaryThresholdValues))] - public void ImageShouldApplyBinaryThresholdInBox(float value) - { - string path = this.CreateOutputDirectory("BinaryThreshold"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.BinaryThreshold(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs index c28732253..a04726871 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs @@ -5,7 +5,7 @@ namespace ImageSharp.Tests { - using Processing; + using ImageSharp.Processing; using System.IO; using ImageSharp.PixelFormats; diff --git a/tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs index 00440e8a5..f3976ae0b 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs @@ -5,7 +5,7 @@ namespace ImageSharp.Tests { - using Processing; + using ImageSharp.Processing; using System.IO; using ImageSharp.PixelFormats; diff --git a/tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs b/tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs index 87f5e1025..c10eac430 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs @@ -9,7 +9,7 @@ namespace ImageSharp.Tests using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Xunit; public class FlipTests : FileTestBase diff --git a/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs b/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs index 31f4020b6..8268c6b64 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs @@ -9,7 +9,7 @@ namespace ImageSharp.Tests using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Xunit; public class ResizeTests : FileTestBase diff --git a/tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs b/tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs index c4c4fa8d7..5f75e98e3 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs @@ -9,7 +9,7 @@ namespace ImageSharp.Tests using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Xunit; public class RotateFlipTest : FileTestBase diff --git a/tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs b/tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs index b30c795ad..8ced88ce6 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs +++ b/tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs @@ -9,7 +9,7 @@ namespace ImageSharp.Tests using ImageSharp.PixelFormats; - using Processing; + using ImageSharp.Processing; using Xunit; public class RotateTest : FileTestBase diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index 44c8c34ee..471d61abb 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -36,9 +36,20 @@ namespace ImageSharp.Tests // Filter changing per scanline public const string FilterVar = "Png/filterVar.png"; - // Odd chunk lengths - public const string ChunkLength1 = "Png/chunklength1.png"; - public const string ChunkLength2 = "Png/chunklength2.png"; + public static class Bad + { + // Odd chunk lengths + public const string ChunkLength1 = "Png/chunklength1.png"; + public const string ChunkLength2 = "Png/chunklength2.png"; + } + + public static readonly string[] All = + { + P1, Pd, Blur, Splash, Cross, + Powerpoint, SplashInterlaced, Interlaced, + Filter0, Filter1, Filter2, Filter3, Filter4, + FilterVar + }; } public static class Jpeg @@ -105,6 +116,8 @@ namespace ImageSharp.Tests public const string Giphy = "Gif/giphy.gif"; public const string Cheers = "Gif/cheers.gif"; public const string Trans = "Gif/trans.gif"; + + public static readonly string[] All = { Rings, Giphy, Cheers, Trans }; } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/ImageDataAttributeBase.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/ImageDataAttributeBase.cs index 379ce3d05..05e8c6136 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Attributes/ImageDataAttributeBase.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/ImageDataAttributeBase.cs @@ -21,25 +21,40 @@ namespace ImageSharp.Tests protected readonly PixelTypes PixelTypes; + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// protected ImageDataAttributeBase(string memberName, PixelTypes pixelTypes, object[] additionalParameters) { this.PixelTypes = pixelTypes; this.AdditionalParameters = additionalParameters; this.MemberName = memberName; - } - public string MemberName { get; private set; } + /// + /// Gets the member name + /// + public string MemberName { get; } + /// + /// Gets the member type + /// public Type MemberType { get; set; } + /// Returns the data to be used to test the theory. + /// The method that is being tested + /// One or more sets of theory data. Each invocation of the test method + /// is represented by a single object array. public override IEnumerable GetData(MethodInfo testMethod) { - IEnumerable addedRows = Enumerable.Empty(); + IEnumerable addedRows = Enumerable.Empty().ToArray(); if (!string.IsNullOrWhiteSpace(this.MemberName)) { Type type = this.MemberType ?? testMethod.DeclaringType; - Func accessor = GetPropertyAccessor(type) ?? GetFieldAccessor(type);// ?? GetMethodAccessor(type); + Func accessor = this.GetPropertyAccessor(type) ?? this.GetFieldAccessor(type); if (accessor != null) { @@ -49,7 +64,7 @@ namespace ImageSharp.Tests addedRows = memberItems.Select(x => x as object[]); if (addedRows.Any(x => x == null)) { - throw new ArgumentException($"Property {MemberName} on {MemberType ?? testMethod.DeclaringType} yielded an item that is not an object[]"); + throw new ArgumentException($"Property {this.MemberName} on {this.MemberType ?? testMethod.DeclaringType} yielded an item that is not an object[]"); } } } @@ -60,18 +75,20 @@ namespace ImageSharp.Tests addedRows = new[] { new object[0] }; } - bool firstIsprovider = FirstIsProvider(testMethod); - IEnumerable dataItems = Enumerable.Empty(); + bool firstIsprovider = this.FirstIsProvider(testMethod); if (firstIsprovider) { - return InnerGetData(testMethod, addedRows); - } - else - { - return addedRows.Select(x => x.Concat(this.AdditionalParameters).ToArray()); + return this.InnerGetData(testMethod, addedRows); } + + return addedRows.Select(x => x.Concat(this.AdditionalParameters).ToArray()); } + /// + /// Returns a value indicating whether the first parameter of the method is a test provider. + /// + /// + /// private bool FirstIsProvider(MethodInfo testMethod) { TypeInfo dataType = testMethod.GetParameters().First().ParameterType.GetTypeInfo(); @@ -106,25 +123,45 @@ namespace ImageSharp.Tests } } + /// + /// Generates the collection of method arguments from the given test as a generic enumerable. + /// + /// The test method + /// The test image provider factory type + /// The protected virtual IEnumerable GetAllFactoryMethodArgs(MethodInfo testMethod, Type factoryType) { object[] args = this.GetFactoryMethodArgs(testMethod, factoryType); return Enumerable.Repeat(args, 1); } + /// + /// Generates the collection of method arguments from the given test. + /// + /// The test method + /// The test image provider factory type + /// The protected virtual object[] GetFactoryMethodArgs(MethodInfo testMethod, Type factoryType) { throw new InvalidOperationException("Semi-abstract method"); } + /// + /// Generates the method name from the given test method. + /// + /// The test method + /// The protected abstract string GetFactoryMethodName(MethodInfo testMethod); + /// + /// Gets the field accessor for the given type. + /// Func GetFieldAccessor(Type type) { FieldInfo fieldInfo = null; for (Type reflectionType = type; reflectionType != null; reflectionType = reflectionType.GetTypeInfo().BaseType) { - fieldInfo = reflectionType.GetRuntimeField(MemberName); + fieldInfo = reflectionType.GetRuntimeField(this.MemberName); if (fieldInfo != null) break; } @@ -135,39 +172,27 @@ namespace ImageSharp.Tests return () => fieldInfo.GetValue(null); } - //Func GetMethodAccessor(Type type) - //{ - // MethodInfo methodInfo = null; - // var parameterTypes = Parameters == null ? new Type[0] : Parameters.Select(p => p?.GetType()).ToArray(); - // for (var reflectionType = type; reflectionType != null; reflectionType = reflectionType.GetTypeInfo().BaseType) - // { - // methodInfo = reflectionType.GetRuntimeMethods() - // .FirstOrDefault(m => m.Name == MemberName && ParameterTypesCompatible(m.GetParameters(), parameterTypes)); - // if (methodInfo != null) - // break; - // } - - // if (methodInfo == null || !methodInfo.IsStatic) - // return null; - - // return () => methodInfo.Invoke(null, Parameters); - //} - + /// + /// Gets the property accessor for the given type. + /// Func GetPropertyAccessor(Type type) { PropertyInfo propInfo = null; for (Type reflectionType = type; reflectionType != null; reflectionType = reflectionType.GetTypeInfo().BaseType) { - propInfo = reflectionType.GetRuntimeProperty(MemberName); + propInfo = reflectionType.GetRuntimeProperty(this.MemberName); if (propInfo != null) + { break; + } } - if (propInfo == null || propInfo.GetMethod == null || !propInfo.GetMethod.IsStatic) + if (propInfo?.GetMethod == null || !propInfo.GetMethod.IsStatic) + { return null; + } return () => propInfo.GetValue(null, null); } - } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithBlankImageAttribute.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithBlankImageAttribute.cs index 32278d755..72be5abc2 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithBlankImageAttribute.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithBlankImageAttribute.cs @@ -31,6 +31,7 @@ namespace ImageSharp.Tests /// /// Triggers passing an that produces a blank image of size width * height /// + /// The member data /// The required width /// The required height /// The requested parameter diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithFileCollectionAttribute.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithFileCollectionAttribute.cs index df8f8d090..6f445dfcc 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithFileCollectionAttribute.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithFileCollectionAttribute.cs @@ -34,37 +34,43 @@ namespace ImageSharp.Tests this.enumeratorMemberName = enumeratorMemberName; } - /// + /// /// Triggers passing instances which read an image for each file being enumerated by the (static) test class field/property defined by enumeratorMemberName /// instances will be passed for each the pixel format defined by the pixelTypes parameter /// /// The name of the static test class field/property enumerating the files + /// The member name /// The requested pixel types /// Additional theory parameter values public WithFileCollectionAttribute( string enumeratorMemberName, - string DataMemberName, + string memberName, PixelTypes pixelTypes, params object[] additionalParameters) - : base(DataMemberName, pixelTypes, additionalParameters) + : base(memberName, pixelTypes, additionalParameters) { this.enumeratorMemberName = enumeratorMemberName; } + /// + /// Generates the collection of method arguments from the given test. + /// + /// The test method + /// The test image provider factory type + /// The protected override IEnumerable GetAllFactoryMethodArgs(MethodInfo testMethod, Type factoryType) { Func accessor = this.GetPropertyAccessor(testMethod.DeclaringType); - accessor = accessor ?? this.GetFieldAccessor(testMethod.DeclaringType); - IEnumerable files = (IEnumerable)accessor(); + var files = (IEnumerable)accessor(); return files.Select(f => new object[] { f }); } protected override string GetFactoryMethodName(MethodInfo testMethod) => "File"; /// - /// Based on MemberData implementation + /// Gets the field accessor for the given type. /// private Func GetFieldAccessor(Type type) { @@ -74,16 +80,22 @@ namespace ImageSharp.Tests reflectionType = reflectionType.GetTypeInfo().BaseType) { fieldInfo = reflectionType.GetRuntimeField(this.enumeratorMemberName); - if (fieldInfo != null) break; + if (fieldInfo != null) + { + break; + } } - if (fieldInfo == null || !fieldInfo.IsStatic) return null; + if (fieldInfo == null || !fieldInfo.IsStatic) + { + return null; + } return () => fieldInfo.GetValue(null); } /// - /// Based on MemberData implementation + /// Gets the property accessor for the given type. /// private Func GetPropertyAccessor(Type type) { @@ -96,7 +108,10 @@ namespace ImageSharp.Tests if (propInfo != null) break; } - if (propInfo == null || propInfo.GetMethod == null || !propInfo.GetMethod.IsStatic) return null; + if (propInfo?.GetMethod == null || !propInfo.GetMethod.IsStatic) + { + return null; + } return () => propInfo.GetValue(null, null); } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs index 4217d52b0..9e8e0dce3 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs @@ -17,7 +17,7 @@ namespace ImageSharp.Tests { private class FileProvider : TestImageProvider, IXunitSerializable { - // Need PixelTypes in the dictionary key, because result images of TestImageProvider.FileProvider + // Need PixelTypes in the dictionary key, because result images of TestImageProvider.FileProvider // are shared between PixelTypes.Color & PixelTypes.StandardImageClass private class Key : Tuple { @@ -27,8 +27,7 @@ namespace ImageSharp.Tests } } - private static ConcurrentDictionary> cache = - new ConcurrentDictionary>(); + private static readonly ConcurrentDictionary> cache = new ConcurrentDictionary>(); private string filePath; diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index dbd316423..064c52064 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -2,33 +2,40 @@ namespace ImageSharp.Tests { using System; - using System.Collections.Generic; using System.Linq; using System.Reflection; - using System.Text; using ImageSharp.PixelFormats; public static class TestImageExtensions { - public static void DebugSave(this Image img, ITestImageProvider provider, object settings = null, string extension = "png") - where TPixel : struct, IPixel + /// + /// Saves the image only when not running in the CI server. + /// + /// The pixel format + /// The image + /// The image provider + /// The settings + /// The extension + public static void DebugSave(this Image image, ITestImageProvider provider, object settings = null, string extension = "png") + where TPixel : struct, IPixel { string tag = null; - if (settings is string) + string s = settings as string; + if (s != null) { - tag = (string)settings; + tag = s; } else if (settings != null) { - var properties = settings.GetType().GetRuntimeProperties(); + System.Collections.Generic.IEnumerable properties = settings.GetType().GetRuntimeProperties(); tag = string.Join("_", properties.ToDictionary(x => x.Name, x => x.GetValue(settings)).Select(x => $"{x.Key}-{x.Value}")); } - if(!bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCI) || !isCI) + if (!bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) || !isCi) { - // we are running locally then we want to save it out - provider.Utility.SaveTestOutputFile(img, extension, tag: tag); + // We are running locally then we want to save it out + provider.Utility.SaveTestOutputFile(image, extension, tag: tag); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs index dfaf1c052..115fb895d 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs @@ -106,6 +106,11 @@ namespace ImageSharp.Tests public static Type ToType(this PixelTypes pixelType) => PixelTypes2ClrTypes[pixelType]; + /// + /// Returns the enumerations for the given type. + /// + /// + /// public static PixelTypes GetPixelType(this Type colorStructClrType) => ClrTypes2PixelTypes[colorStructClrType]; public static IEnumerable> ExpandAllTypes(this PixelTypes pixelTypes) From 99fa20b97e37f36ce5f25b4c9f72666dacba5347 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 20:12:44 +1000 Subject: [PATCH 39/84] Remove Vector4 <-> RectangleF cast. --- src/ImageSharp/Numerics/RectangleF.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/ImageSharp/Numerics/RectangleF.cs b/src/ImageSharp/Numerics/RectangleF.cs index 28d887c5d..7611c9602 100644 --- a/src/ImageSharp/Numerics/RectangleF.cs +++ b/src/ImageSharp/Numerics/RectangleF.cs @@ -164,20 +164,6 @@ namespace ImageSharp } } - /// - /// Creates a with the coordinates of the specified . - /// - /// The rectangle - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator RectangleF(Vector4 vector) => new RectangleF(vector.X, vector.Y, vector.Z, vector.W); - - /// - /// Creates a with the coordinates of the specified . - /// - /// The rectangle - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Vector4(RectangleF rectangle) => new Vector4(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height); - /// /// Creates a with the coordinates of the specified by truncating each coordinate. /// From 6cea382a72a82a2f56172dda7a9125fc61497e42 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 22:17:46 +1000 Subject: [PATCH 40/84] Finish dither tests --- .../Binarization/BinaryThresholdTest.cs | 15 +++- .../Processing/Binarization/DitherTest.cs | 86 +++++++++---------- .../Attributes/WithFileCollectionAttribute.cs | 17 ++-- .../TestUtilities/TestImageExtensions.cs | 12 ++- 4 files changed, 70 insertions(+), 60 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs index f3dcbe1cd..7286375ba 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs @@ -11,20 +11,27 @@ namespace ImageSharp.Tests.Processing.Binarization public class BinaryThresholdTest : FileTestBase { + public static readonly TheoryData BinaryThresholdValues + = new TheoryData + { + .25F, + .75F + }; + [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes, .75F)] + [WithFileCollection(nameof(AllBmpFiles), nameof(BinaryThresholdValues), StandardPixelTypes)] public void ImageShouldApplyBinaryThresholdFilter(TestImageProvider provider, float value) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { image.BinaryThreshold(value) - .DebugSave(provider, null, Extensions.Bmp); + .DebugSave(provider, value, Extensions.Bmp); } } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes, .75F)] + [WithFileCollection(nameof(AllBmpFiles), nameof(BinaryThresholdValues), StandardPixelTypes)] public void ImageShouldApplyBinaryThresholdInBox(TestImageProvider provider, float value) where TPixel : struct, IPixel { @@ -35,7 +42,7 @@ namespace ImageSharp.Tests.Processing.Binarization var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); image.BinaryThreshold(value, bounds) - .DebugSave(provider, null, Extensions.Bmp); + .DebugSave(provider, value, Extensions.Bmp); // Draw identical shapes over the bounded and compare to ensure changes are constrained. image.Fill(NamedColors.HotPink, bounds); diff --git a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs index 066e2d134..c88227b2c 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs @@ -5,8 +5,6 @@ namespace ImageSharp.Tests { - using System.IO; - using ImageSharp.Dithering; using ImageSharp.Dithering.Ordered; using ImageSharp.PixelFormats; @@ -34,70 +32,66 @@ namespace ImageSharp.Tests }; [Theory] - [MemberData(nameof(Ditherers))] - public void ImageShouldApplyDitherFilter(string name, IOrderedDither ditherer) + [WithFileCollection(nameof(AllBmpFiles), nameof(Ditherers), StandardPixelTypes)] + public void ImageShouldApplyDitherFilter(TestImageProvider provider, string name, IOrderedDither ditherer) + where TPixel : struct, IPixel { - string path = this.CreateOutputDirectory("Dither", "Dither"); - - foreach (TestFile file in Files) + using (Image image = provider.GetImage()) { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Dither(ditherer).Save(output); - } + image.Dither(ditherer) + .DebugSave(provider, name, Extensions.Bmp); } } [Theory] - [MemberData(nameof(Ditherers))] - public void ImageShouldApplyDitherFilterInBox(string name, IOrderedDither ditherer) + [WithFileCollection(nameof(AllBmpFiles), nameof(Ditherers), StandardPixelTypes)] + public void ImageShouldApplyDitherFilterInBox(TestImageProvider provider, string name, IOrderedDither ditherer) + where TPixel : struct, IPixel { - string path = this.CreateOutputDirectory("Dither", "Dither"); - - foreach (TestFile file in Files) + using (Image source = provider.GetImage()) + using (var image = new Image(source)) { - string filename = file.GetFileName($"{name}-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Dither(ditherer, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Dither(ditherer, bounds) + .DebugSave(provider, name, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); } } [Theory] - [MemberData(nameof(ErrorDiffusers))] - public void ImageShouldApplyDiffusionFilter(string name, IErrorDiffuser diffuser) + [WithFileCollection(nameof(AllBmpFiles), nameof(ErrorDiffusers), StandardPixelTypes)] + public void ImageShouldApplyDiffusionFilter(TestImageProvider provider, string name, IErrorDiffuser diffuser) + where TPixel : struct, IPixel { - string path = this.CreateOutputDirectory("Dither", "Diffusion"); - - foreach (TestFile file in Files) + using (Image image = provider.GetImage()) { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Dither(diffuser, .5F).Save(output); - } + image.Dither(diffuser, .5F) + .DebugSave(provider, name, Extensions.Bmp); } } [Theory] - [MemberData(nameof(ErrorDiffusers))] - public void ImageShouldApplyDiffusionFilterInBox(string name, IErrorDiffuser diffuser) + [WithFileCollection(nameof(AllBmpFiles), nameof(ErrorDiffusers), StandardPixelTypes)] + public void ImageShouldApplyDiffusionFilterInBox(TestImageProvider provider, string name, IErrorDiffuser diffuser) + where TPixel : struct, IPixel { - string path = this.CreateOutputDirectory("Dither", "Diffusion"); - - foreach (TestFile file in Files) + using (Image source = provider.GetImage()) + using (var image = new Image(source)) { - string filename = file.GetFileName($"{name}-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Dither(diffuser, .5F, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Dither(diffuser,.5F, bounds) + .DebugSave(provider, name, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithFileCollectionAttribute.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithFileCollectionAttribute.cs index 6f445dfcc..1b37c45a9 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithFileCollectionAttribute.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithFileCollectionAttribute.cs @@ -16,22 +16,22 @@ namespace ImageSharp.Tests /// public class WithFileCollectionAttribute : ImageDataAttributeBase { - private readonly string enumeratorMemberName; + private readonly string fileEnumeratorMemberName; /// /// Triggers passing instances which read an image for each file being enumerated by the (static) test class field/property defined by enumeratorMemberName /// instances will be passed for each the pixel format defined by the pixelTypes parameter /// - /// The name of the static test class field/property enumerating the files + /// The name of the static test class field/property enumerating the files /// The requested pixel types /// Additional theory parameter values public WithFileCollectionAttribute( - string enumeratorMemberName, + string fileEnumeratorMemberName, PixelTypes pixelTypes, params object[] additionalParameters) : base(null, pixelTypes, additionalParameters) { - this.enumeratorMemberName = enumeratorMemberName; + this.fileEnumeratorMemberName = fileEnumeratorMemberName; } /// @@ -39,7 +39,7 @@ namespace ImageSharp.Tests /// instances will be passed for each the pixel format defined by the pixelTypes parameter /// /// The name of the static test class field/property enumerating the files - /// The member name + /// The member name for enumerating method parameters /// The requested pixel types /// Additional theory parameter values public WithFileCollectionAttribute( @@ -49,7 +49,7 @@ namespace ImageSharp.Tests params object[] additionalParameters) : base(memberName, pixelTypes, additionalParameters) { - this.enumeratorMemberName = enumeratorMemberName; + this.fileEnumeratorMemberName = enumeratorMemberName; } /// @@ -67,6 +67,7 @@ namespace ImageSharp.Tests return files.Select(f => new object[] { f }); } + /// protected override string GetFactoryMethodName(MethodInfo testMethod) => "File"; /// @@ -79,7 +80,7 @@ namespace ImageSharp.Tests reflectionType != null; reflectionType = reflectionType.GetTypeInfo().BaseType) { - fieldInfo = reflectionType.GetRuntimeField(this.enumeratorMemberName); + fieldInfo = reflectionType.GetRuntimeField(this.fileEnumeratorMemberName); if (fieldInfo != null) { break; @@ -104,7 +105,7 @@ namespace ImageSharp.Tests reflectionType != null; reflectionType = reflectionType.GetTypeInfo().BaseType) { - propInfo = reflectionType.GetRuntimeProperty(this.enumeratorMemberName); + propInfo = reflectionType.GetRuntimeProperty(this.fileEnumeratorMemberName); if (propInfo != null) break; } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 064c52064..1c5038014 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -2,6 +2,7 @@ namespace ImageSharp.Tests { using System; + using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -28,9 +29,16 @@ namespace ImageSharp.Tests } else if (settings != null) { - System.Collections.Generic.IEnumerable properties = settings.GetType().GetRuntimeProperties(); + if (settings.GetType().GetTypeInfo().IsPrimitive) + { + tag = settings.ToString(); + } + else + { + IEnumerable properties = settings.GetType().GetRuntimeProperties(); - tag = string.Join("_", properties.ToDictionary(x => x.Name, x => x.GetValue(settings)).Select(x => $"{x.Key}-{x.Value}")); + tag = string.Join("_", properties.ToDictionary(x => x.Name, x => x.GetValue(settings)).Select(x => $"{x.Key}-{x.Value}")); + } } if (!bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) || !isCi) { From fe040bbdacadb0bb78ce88738884c5d2df4c0682 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 23:01:51 +1000 Subject: [PATCH 41/84] BlackWhite, ColorBlindness, Grayscale --- tests/ImageSharp.Tests/FileTestBase.cs | 2 +- .../Processing/ColorMatrix/BlackWhiteTest.cs | 46 +++++++++++++ .../ColorMatrix/ColorBlindnessTest.cs | 60 +++++++++++++++++ .../ColorMatrix}/GrayscaleTest.cs | 31 +++++---- .../Processors/Filters/BlackWhiteTest.cs | 47 -------------- .../Processors/Filters/ColorBlindnessTest.cs | 64 ------------------- .../WithTestPatternImageAttribute.cs | 8 +++ .../TestUtilities/TestImageExtensions.cs | 20 ++++-- 8 files changed, 147 insertions(+), 131 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs rename tests/ImageSharp.Tests/{Processors/Filters => Processing/ColorMatrix}/GrayscaleTest.cs (63%) delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/BlackWhiteTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs index 4316efdd8..654cdf64e 100644 --- a/tests/ImageSharp.Tests/FileTestBase.cs +++ b/tests/ImageSharp.Tests/FileTestBase.cs @@ -35,7 +35,7 @@ namespace ImageSharp.Tests /// /// The standard pixel formats enumerations /// - public const PixelTypes StandardPixelTypes = PixelTypes.StandardImageClass | PixelTypes.Rgba32 | PixelTypes.Argb32; + public const PixelTypes StandardPixelTypes = PixelTypes.StandardImageClass | PixelTypes.Rgba32; public static class Extensions { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs new file mode 100644 index 000000000..cc9c42d51 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.ColorMatrix +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class BlackWhiteTest : FileTestBase + { + [Fact] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplyBlackWhiteFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.BlackWhite() + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Fact] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplyBlackWhiteFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.BlackWhite(bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs new file mode 100644 index 000000000..4a8273281 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs @@ -0,0 +1,60 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.ColorMatrix +{ + using ImageSharp.PixelFormats; + using ImageSharp.Processing; + + using Xunit; + + public class ColorBlindnessTest : FileTestBase + { + public static readonly TheoryData ColorBlindnessFilters + = new TheoryData + { + ColorBlindness.Achromatomaly, + ColorBlindness.Achromatopsia, + ColorBlindness.Deuteranomaly, + ColorBlindness.Deuteranopia, + ColorBlindness.Protanomaly, + ColorBlindness.Protanopia, + ColorBlindness.Tritanomaly, + ColorBlindness.Tritanopia + }; + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(ColorBlindnessFilters), StandardPixelTypes)] + public void ImageShouldApplyColorBlindnessFilter(TestImageProvider provider, ColorBlindness colorBlindness) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.ColorBlindness(colorBlindness) + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(ColorBlindnessFilters), StandardPixelTypes)] + public void ImageShouldApplyColorBlindnessFilterInBox(TestImageProvider provider, ColorBlindness colorBlindness) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.ColorBlindness(colorBlindness, bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs similarity index 63% rename from tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs rename to tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs index 2e82191ec..be0983df8 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/GrayscaleTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs @@ -3,21 +3,27 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp.Tests +namespace ImageSharp.Tests.Processing.ColorMatrix { - using Xunit; + using ImageSharp.PixelFormats; using ImageSharp.Processing; - using ImageSharp.PixelFormats; + using Xunit; public class GrayscaleTest : FileTestBase { + public static readonly TheoryData GrayscaleModeTypes + = new TheoryData + { + GrayscaleMode.Bt601, + GrayscaleMode.Bt709 + }; + /// /// Use test patterns over loaded images to save decode time. /// [Theory] - [WithTestPatternImages(50, 50, PixelTypes.StandardImageClass, GrayscaleMode.Bt709)] - [WithTestPatternImages(50, 50, PixelTypes.StandardImageClass, GrayscaleMode.Bt601)] + [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, StandardPixelTypes)] public void ImageShouldApplyGrayscaleFilterAll(TestImageProvider provider, GrayscaleMode value) where TPixel : struct, IPixel { @@ -37,21 +43,20 @@ namespace ImageSharp.Tests } [Theory] - [WithTestPatternImages(50, 50, PixelTypes.StandardImageClass, GrayscaleMode.Bt709)] - [WithTestPatternImages(50, 50, PixelTypes.StandardImageClass, GrayscaleMode.Bt601)] + [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, StandardPixelTypes)] public void ImageShouldApplyGrayscaleFilterInBox(TestImageProvider provider, GrayscaleMode value) where TPixel : struct, IPixel { using (Image source = provider.GetImage()) - using (Image image = new Image(source)) + using (var image = new Image(source)) { - Rectangle rect = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); - image.Grayscale(rect, value) + var bounds = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); + image.Grayscale(bounds, value) .DebugSave(provider, value.ToString()); - // Let's draw identical shapes over the greyed areas and ensure that it didn't change the outer area - image.Fill(NamedColors.HotPink, rect); - source.Fill(NamedColors.HotPink, rect); + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); ImageComparer.CheckSimilarity(image, source); } } diff --git a/tests/ImageSharp.Tests/Processors/Filters/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processors/Filters/BlackWhiteTest.cs deleted file mode 100644 index d10698a99..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/BlackWhiteTest.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class BlackWhiteTest : FileTestBase - { - [Fact] - public void ImageShouldApplyBlackWhiteFilter() - { - string path = this.CreateOutputDirectory("BlackWhite"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.BlackWhite().Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyBlackWhiteFilterInBox() - { - string path = this.CreateOutputDirectory("BlackWhite"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.BlackWhite(new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs deleted file mode 100644 index a04726871..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/ColorBlindnessTest.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using ImageSharp.Processing; - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class ColorBlindnessTest : FileTestBase - { - public static readonly TheoryData ColorBlindnessFilters - = new TheoryData - { - ColorBlindness.Achromatomaly, - ColorBlindness.Achromatopsia, - ColorBlindness.Deuteranomaly, - ColorBlindness.Deuteranopia, - ColorBlindness.Protanomaly, - ColorBlindness.Protanopia, - ColorBlindness.Tritanomaly, - ColorBlindness.Tritanopia - }; - - [Theory] - [MemberData(nameof(ColorBlindnessFilters))] - public void ImageShouldApplyColorBlindnessFilter(ColorBlindness colorBlindness) - { - string path = this.CreateOutputDirectory("ColorBlindness"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(colorBlindness); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.ColorBlindness(colorBlindness).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ColorBlindnessFilters))] - public void ImageShouldApplyBrightnessFilterInBox(ColorBlindness colorBlindness) - { - string path = this.CreateOutputDirectory("ColorBlindness"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(colorBlindness + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.ColorBlindness(colorBlindness, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithTestPatternImageAttribute.cs b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithTestPatternImageAttribute.cs index 77c60a943..f6ab65f71 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Attributes/WithTestPatternImageAttribute.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Attributes/WithTestPatternImageAttribute.cs @@ -29,6 +29,7 @@ namespace ImageSharp.Tests /// /// Triggers passing an that produces a test pattern image of size width * height /// + /// The member data to apply to theories /// The required width /// The required height /// The requested parameter @@ -40,7 +41,14 @@ namespace ImageSharp.Tests this.Height = height; } + /// + /// Gets the width + /// public int Width { get; } + + /// + /// Gets the height + /// public int Height { get; } protected override string GetFactoryMethodName(MethodInfo testMethod) => "TestPattern"; diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 1c5038014..f55cfbf16 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -1,4 +1,8 @@ - +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + namespace ImageSharp.Tests { using System; @@ -21,8 +25,15 @@ namespace ImageSharp.Tests public static void DebugSave(this Image image, ITestImageProvider provider, object settings = null, string extension = "png") where TPixel : struct, IPixel { + if (bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) && isCi) + { + return; + } + + // We are running locally then we want to save it out string tag = null; string s = settings as string; + if (s != null) { tag = s; @@ -40,11 +51,8 @@ namespace ImageSharp.Tests tag = string.Join("_", properties.ToDictionary(x => x.Name, x => x.GetValue(settings)).Select(x => $"{x.Key}-{x.Value}")); } } - if (!bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) || !isCi) - { - // We are running locally then we want to save it out - provider.Utility.SaveTestOutputFile(image, extension, tag: tag); - } + + provider.Utility.SaveTestOutputFile(image, extension, tag: tag); } } } From 1ca02ea0146affe4faadb4551dbd2a48de2fe9cc Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 23:21:35 +1000 Subject: [PATCH 42/84] Fix Grayscale param order --- .../Processing/ColorMatrix/Grayscale.cs | 40 ++++++++++++++++--- .../Processing/ColorMatrix/GrayscaleTest.cs | 2 +- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/ImageSharp/Processing/ColorMatrix/Grayscale.cs b/src/ImageSharp/Processing/ColorMatrix/Grayscale.cs index 89bc2a947..daddf106c 100644 --- a/src/ImageSharp/Processing/ColorMatrix/Grayscale.cs +++ b/src/ImageSharp/Processing/ColorMatrix/Grayscale.cs @@ -5,8 +5,6 @@ namespace ImageSharp { - using System; - using ImageSharp.PixelFormats; using ImageSharp.Processing; @@ -17,6 +15,18 @@ namespace ImageSharp /// public static partial class ImageExtensions { + /// + /// Applies Grayscale toning to the image. + /// + /// The pixel format. + /// The image this method extends. + /// The . + public static Image Grayscale(this Image source) + where TPixel : struct, IPixel + { + return Grayscale(source, GrayscaleMode.Bt709); + } + /// /// Applies Grayscale toning to the image. /// @@ -24,23 +34,41 @@ namespace ImageSharp /// The image this method extends. /// The formula to apply to perform the operation. /// The . - public static Image Grayscale(this Image source, GrayscaleMode mode = GrayscaleMode.Bt709) + public static Image Grayscale(this Image source, GrayscaleMode mode) where TPixel : struct, IPixel { - return Grayscale(source, source.Bounds, mode); + return Grayscale(source, mode, source.Bounds); } /// - /// Applies Grayscale toning to the image. + /// Applies Grayscale toning to the image. /// /// The pixel format. /// The image this method extends. /// /// The structure that specifies the portion of the image object to alter. /// + /// The . + public static Image Grayscale(this Image source, Rectangle rectangle) + where TPixel : struct, IPixel + { + IImageProcessor processor = new GrayscaleBt709Processor(); + + source.ApplyProcessor(processor, rectangle); + return source; + } + + /// + /// Applies Grayscale toning to the image. + /// + /// The pixel format. + /// The image this method extends. /// The formula to apply to perform the operation. + /// + /// The structure that specifies the portion of the image object to alter. + /// /// The . - public static Image Grayscale(this Image source, Rectangle rectangle, GrayscaleMode mode = GrayscaleMode.Bt709) + public static Image Grayscale(this Image source, GrayscaleMode mode, Rectangle rectangle) where TPixel : struct, IPixel { IImageProcessor processor = mode == GrayscaleMode.Bt709 diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs index be0983df8..c68b7c5c3 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs @@ -51,7 +51,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix using (var image = new Image(source)) { var bounds = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); - image.Grayscale(bounds, value) + image.Grayscale(value, bounds) .DebugSave(provider, value.ToString()); // Draw identical shapes over the bounded and compare to ensure changes are constrained. From fb173db2ca2a96874770f5d275166991da6d43ed Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 23:30:30 +1000 Subject: [PATCH 43/84] Hue --- .../Processing/ColorMatrix/HueTest.cs | 53 +++++++++++++++++ .../Processors/Filters/HueTest.cs | 57 ------------------- 2 files changed, 53 insertions(+), 57 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/HueTest.cs diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs new file mode 100644 index 000000000..1e0760194 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.ColorMatrix +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class HueTest : FileTestBase + { + public static readonly TheoryData HueValues + = new TheoryData + { + 180, + -180 + }; + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(HueValues), StandardPixelTypes)] + public void ImageShouldApplyHueFilter(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Hue(value) + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(HueValues), StandardPixelTypes)] + public void ImageShouldApplyHueFilterInBox(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Hue(value, bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/HueTest.cs b/tests/ImageSharp.Tests/Processors/Filters/HueTest.cs deleted file mode 100644 index 488433931..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/HueTest.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class HueTest : FileTestBase - { - public static readonly TheoryData HueValues - = new TheoryData - { - 180 , - -180 , - }; - - [Theory] - [MemberData(nameof(HueValues))] - public void ImageShouldApplyHueFilter(int value) - { - string path = this.CreateOutputDirectory("Hue"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Hue(value).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(HueValues))] - public void ImageShouldApplyHueFilterInBox(int value) - { - string path = this.CreateOutputDirectory("Hue"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Hue(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From 2fdd5d2af9a734902061de4c5d6ab2422cf834f8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 23:43:35 +1000 Subject: [PATCH 44/84] Kodachrome --- .../Processing/ColorMatrix/BlackWhiteTest.cs | 4 +- .../Processing/ColorMatrix/KodachromeTest.cs | 46 ++++++++++++++++++ .../Processors/Filters/KodachromeTest.cs | 47 ------------------- 3 files changed, 48 insertions(+), 49 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/KodachromeTest.cs diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs index cc9c42d51..e3083cbe1 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs @@ -11,7 +11,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class BlackWhiteTest : FileTestBase { - [Fact] + [Theory] [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] public void ImageShouldApplyBlackWhiteFilter(TestImageProvider provider) where TPixel : struct, IPixel @@ -23,7 +23,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } } - [Fact] + [Theory] [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] public void ImageShouldApplyBlackWhiteFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs new file mode 100644 index 000000000..ece3eb41a --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.ColorMatrix +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class KodachromeTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplyKodachromeFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Kodachrome() + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplyKodachromeFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Kodachrome(bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/KodachromeTest.cs b/tests/ImageSharp.Tests/Processors/Filters/KodachromeTest.cs deleted file mode 100644 index 29a459f97..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/KodachromeTest.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class KodachromeTest : FileTestBase - { - [Fact] - public void ImageShouldApplyKodachromeFilter() - { - string path = this.CreateOutputDirectory("Kodachrome"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Kodachrome().Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyKodachromeFilterInBox() - { - string path = this.CreateOutputDirectory("Kodachrome"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Kodachrome(new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From 33a46c13e1e5984e863963fdcb7ed22ef6166231 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 23:49:59 +1000 Subject: [PATCH 45/84] Lomograph --- .../ColorMatrix/ColorBlindnessTest.cs | 4 +- .../Processing/ColorMatrix/HueTest.cs | 4 +- .../Processing/ColorMatrix/LomographTest.cs | 48 +++++++++++++++++++ .../Processors/Filters/LomographTest.cs | 48 ------------------- 4 files changed, 52 insertions(+), 52 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/LomographTest.cs diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs index 4a8273281..24df04fdf 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs @@ -33,7 +33,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix using (Image image = provider.GetImage()) { image.ColorBlindness(colorBlindness) - .DebugSave(provider, null, Extensions.Bmp); + .DebugSave(provider, colorBlindness.ToString(), Extensions.Bmp); } } @@ -48,7 +48,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); image.ColorBlindness(colorBlindness, bounds) - .DebugSave(provider, null, Extensions.Bmp); + .DebugSave(provider, colorBlindness.ToString(), Extensions.Bmp); // Draw identical shapes over the bounded and compare to ensure changes are constrained. image.Fill(NamedColors.HotPink, bounds); diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs index 1e0760194..9b6510631 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs @@ -26,7 +26,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix using (Image image = provider.GetImage()) { image.Hue(value) - .DebugSave(provider, null, Extensions.Bmp); + .DebugSave(provider, value, Extensions.Bmp); } } @@ -41,7 +41,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); image.Hue(value, bounds) - .DebugSave(provider, null, Extensions.Bmp); + .DebugSave(provider, value, Extensions.Bmp); // Draw identical shapes over the bounded and compare to ensure changes are constrained. image.Fill(NamedColors.HotPink, bounds); diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs new file mode 100644 index 000000000..2ea686fd9 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs @@ -0,0 +1,48 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests +{ + using System.IO; + + using ImageSharp.PixelFormats; + + using Xunit; + + public class LomographTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplyLomographFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Lomograph() + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplyLomographFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Lomograph(bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/LomographTest.cs b/tests/ImageSharp.Tests/Processors/Filters/LomographTest.cs deleted file mode 100644 index 6ceedecbd..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/LomographTest.cs +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class LomographTest : FileTestBase - { - [Fact] - public void ImageShouldApplyLomographFilter() - { - string path = this.CreateOutputDirectory("Lomograph"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Lomograph().Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyLomographFilterInBox() - { - string path = this.CreateOutputDirectory("Lomograph"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Lomograph(new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file From 792bd7deca04427edeedfed60d032d27ccd5ed0e Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 23:54:42 +1000 Subject: [PATCH 46/84] Polaroid --- .../Processing/ColorMatrix/PolaroidTest.cs | 46 ++++++++++++++++++ .../Processors/Filters/PolaroidTest.cs | 47 ------------------- 2 files changed, 46 insertions(+), 47 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/PolaroidTest.cs diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs new file mode 100644 index 000000000..1803fb581 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.ColorMatrix +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class PolaroidTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplyPolaroidFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Polaroid() + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplyPolaroidFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Polaroid(bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/PolaroidTest.cs b/tests/ImageSharp.Tests/Processors/Filters/PolaroidTest.cs deleted file mode 100644 index df3803255..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/PolaroidTest.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class PolaroidTest : FileTestBase - { - [Fact] - public void ImageShouldApplyPolaroidFilter() - { - string path = this.CreateOutputDirectory("Polaroid"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Polaroid().Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyPolaroidFilterInBox() - { - string path = this.CreateOutputDirectory("Polaroid"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Polaroid(new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From 72ea45b38c191c6d80642394b1522619cac4d5c3 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 29 May 2017 23:58:57 +1000 Subject: [PATCH 47/84] Saturation --- .../Processing/ColorMatrix/SaturationTest.cs | 53 +++++++++++++++++ .../Processors/Filters/SaturationTest.cs | 57 ------------------- 2 files changed, 53 insertions(+), 57 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/SaturationTest.cs diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs new file mode 100644 index 000000000..506f29503 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.ColorMatrix +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class SaturationTest : FileTestBase + { + public static readonly TheoryData SaturationValues + = new TheoryData + { + 50 , + -50 , + }; + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(SaturationValues), StandardPixelTypes)] + public void ImageShouldApplySaturationFilter(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Saturation(value) + .DebugSave(provider, value, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(SaturationValues), StandardPixelTypes)] + public void ImageShouldApplySaturationFilterInBox(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Saturation(value, bounds) + .DebugSave(provider, value, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/SaturationTest.cs b/tests/ImageSharp.Tests/Processors/Filters/SaturationTest.cs deleted file mode 100644 index e28847fa3..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/SaturationTest.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class SaturationTest : FileTestBase - { - public static readonly TheoryData SaturationValues - = new TheoryData - { - 50 , - -50 , - }; - - [Theory] - [MemberData(nameof(SaturationValues))] - public void ImageShouldApplySaturationFilter(int value) - { - string path = CreateOutputDirectory("Saturation"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Saturation(value).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(SaturationValues))] - public void ImageShouldApplySaturationFilterInBox(int value) - { - string path = this.CreateOutputDirectory("Saturation"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Saturation(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From 25bcbc74b1bc0e3b4d62173dda505dae50e7b643 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 00:02:20 +1000 Subject: [PATCH 48/84] Sepia --- .../Processing/ColorMatrix/SepiaTest.cs | 46 ++++++++++++++++++ .../Processors/Filters/SepiaTest.cs | 47 ------------------- 2 files changed, 46 insertions(+), 47 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/SepiaTest.cs diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs new file mode 100644 index 000000000..b129ffe56 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.ColorMatrix +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class SepiaTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplySepiaFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Sepia() + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + public void ImageShouldApplySepiaFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Sepia(bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/SepiaTest.cs b/tests/ImageSharp.Tests/Processors/Filters/SepiaTest.cs deleted file mode 100644 index 490213ce7..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/SepiaTest.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class SepiaTest : FileTestBase - { - [Fact] - public void ImageShouldApplySepiaFilter() - { - string path = CreateOutputDirectory("Sepia"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Sepia().Save(output); - } - } - } - - [Fact] - public void ImageShouldApplySepiaFilterInBox() - { - string path = this.CreateOutputDirectory("Sepia"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Sepia(new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From f7b8491e60c7c58dc0c083fc6d7d9a19172c0660 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 00:38:55 +1000 Subject: [PATCH 49/84] Blur, Sharpen --- .../Processing/Convolution/BoxBlurTest.cs | 53 +++++++++++++++++ .../Convolution}/GaussianBlurTest.cs | 31 +++++----- .../Convolution}/GaussianSharpenTest.cs | 31 +++++----- .../Processors/Filters/BoxBlurTest.cs | 57 ------------------- 4 files changed, 85 insertions(+), 87 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs rename tests/ImageSharp.Tests/{Processors/Filters => Processing/Convolution}/GaussianBlurTest.cs (53%) rename tests/ImageSharp.Tests/{Processors/Filters => Processing/Convolution}/GaussianSharpenTest.cs (53%) delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/BoxBlurTest.cs diff --git a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs new file mode 100644 index 000000000..f19e6cd0c --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Convolution +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class BoxBlurTest : FileTestBase + { + public static readonly TheoryData BoxBlurValues + = new TheoryData + { + 3, + 5 + }; + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(BoxBlurValues), StandardPixelTypes)] + public void ImageShouldApplyBoxBlurFilter(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.BoxBlur(value) + .DebugSave(provider, value, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(BoxBlurValues), StandardPixelTypes)] + public void ImageShouldApplyBoxBlurFilterInBox(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.BoxBlur(value, bounds) + .DebugSave(provider, value, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs similarity index 53% rename from tests/ImageSharp.Tests/Processors/Filters/GaussianBlurTest.cs rename to tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs index 4b2ac8b7c..d80daf1d6 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs @@ -3,48 +3,49 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp.Tests +namespace ImageSharp.Tests.Processing.Convolution { - using System.IO; using ImageSharp.PixelFormats; + using Xunit; - public class GaussianBlurTest + public class GaussianBlurTest : FileTestBase { public static readonly TheoryData GaussianBlurValues = new TheoryData { - 3 , - 5 , + 3, + 5 }; [Theory] - [WithTestPatternImages(nameof(GaussianBlurValues), 320, 240, PixelTypes.StandardImageClass)] + [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianBlurValues), StandardPixelTypes)] public void ImageShouldApplyGaussianBlurFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { image.GaussianBlur(value) - .DebugSave(provider, value.ToString()); + .DebugSave(provider, value, Extensions.Bmp); } } [Theory] - [WithTestPatternImages(nameof(GaussianBlurValues), 320, 240, PixelTypes.StandardImageClass)] + [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianBlurValues), StandardPixelTypes)] public void ImageShouldApplyGaussianBlurFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { using (Image source = provider.GetImage()) - using (Image image = new Image(source)) + using (var image = new Image(source)) { - Rectangle rect = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); - image.GaussianBlur(value, rect) - .DebugSave(provider, value.ToString()); + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.GaussianBlur(value, bounds) + .DebugSave(provider, value, Extensions.Bmp); - // lets draw identical shapes over the blured areas and ensure that it didn't change the outer area - image.Fill(NamedColors.HotPink, rect); - source.Fill(NamedColors.HotPink, rect); + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); ImageComparer.CheckSimilarity(image, source); } } diff --git a/tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs similarity index 53% rename from tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs rename to tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs index 1fa1ae15c..1632e2c2f 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs @@ -3,10 +3,10 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp.Tests +namespace ImageSharp.Tests.Processing.Convolution { - using System.IO; using ImageSharp.PixelFormats; + using Xunit; public class GaussianSharpenTest : FileTestBase @@ -14,37 +14,38 @@ namespace ImageSharp.Tests public static readonly TheoryData GaussianSharpenValues = new TheoryData { - 3 , - 5 , + 3, + 5 }; [Theory] - [WithTestPatternImages(nameof(GaussianSharpenValues), 320, 240, PixelTypes.StandardImageClass)] + [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianSharpenValues), StandardPixelTypes)] public void ImageShouldApplyGaussianSharpenFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { using (Image image = provider.GetImage()) { image.GaussianSharpen(value) - .DebugSave(provider, value.ToString()); + .DebugSave(provider, value, Extensions.Bmp); } } [Theory] - [WithTestPatternImages(nameof(GaussianSharpenValues), 320, 240, PixelTypes.StandardImageClass)] + [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianSharpenValues), StandardPixelTypes)] public void ImageShouldApplyGaussianSharpenFilterInBox(TestImageProvider provider, int value) - where TPixel : struct, IPixel + where TPixel : struct, IPixel { using (Image source = provider.GetImage()) - using (Image image = new Image(source)) + using (var image = new Image(source)) { - Rectangle rect = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); - image.GaussianSharpen(value, rect) - .DebugSave(provider, value.ToString()); + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.GaussianSharpen(value, bounds) + .DebugSave(provider, value, Extensions.Bmp); - // lets draw identical shapes over the Sharpened areas and ensure that it didn't change the outer area - image.Fill(NamedColors.HotPink, rect); - source.Fill(NamedColors.HotPink, rect); + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); ImageComparer.CheckSimilarity(image, source); } } diff --git a/tests/ImageSharp.Tests/Processors/Filters/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processors/Filters/BoxBlurTest.cs deleted file mode 100644 index 03226a961..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/BoxBlurTest.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class BoxBlurTest : FileTestBase - { - public static readonly TheoryData BoxBlurValues - = new TheoryData - { - 3 , - 5 , - }; - - [Theory] - [MemberData(nameof(BoxBlurValues))] - public void ImageShouldApplyBoxBlurFilter(int value) - { - string path = this.CreateOutputDirectory("BoxBlur"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.BoxBlur(value).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(BoxBlurValues))] - public void ImageShouldApplyBoxBlurFilterInBox(int value) - { - string path = this.CreateOutputDirectory("BoxBlur"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.BoxBlur(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From cbdd979f019e08318016334a9c05d0157bf85a41 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 00:58:48 +1000 Subject: [PATCH 50/84] Detect edges --- .../Processing/Convolution/DetectEdgesTest.cs | 62 +++++++++++++++++ .../Processors/Filters/DetectEdgesTest.cs | 67 ------------------- 2 files changed, 62 insertions(+), 67 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs new file mode 100644 index 000000000..4e5a230ec --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs @@ -0,0 +1,62 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Convolution +{ + using ImageSharp.PixelFormats; + using ImageSharp.Processing; + + using Xunit; + + public class DetectEdgesTest : FileTestBase + { + public static readonly TheoryData DetectEdgesFilters + = new TheoryData + { + EdgeDetection.Kayyali, + EdgeDetection.Kirsch, + EdgeDetection.Lapacian3X3, + EdgeDetection.Lapacian5X5, + EdgeDetection.LaplacianOfGaussian, + EdgeDetection.Prewitt, + EdgeDetection.RobertsCross, + EdgeDetection.Robinson, + EdgeDetection.Scharr, + EdgeDetection.Sobel + }; + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(DetectEdgesFilters), StandardPixelTypes)] + public void ImageShouldApplyDetectEdgesFilter(TestImageProvider provider, EdgeDetection detector) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.DetectEdges(detector) + .DebugSave(provider, detector.ToString(), Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(AllBmpFiles), nameof(DetectEdgesFilters), StandardPixelTypes)] + public void ImageShouldApplyDetectEdgesFilterInBox(TestImageProvider provider, EdgeDetection detector) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.DetectEdges(detector, bounds) + .DebugSave(provider, detector.ToString(), Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs deleted file mode 100644 index f3976ae0b..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using ImageSharp.Processing; - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class DetectEdgesTest : FileTestBase - { - public static readonly TheoryData DetectEdgesFilters - = new TheoryData - { - EdgeDetection.Kayyali, - EdgeDetection.Kirsch, - EdgeDetection.Lapacian3X3, - EdgeDetection.Lapacian5X5, - EdgeDetection.LaplacianOfGaussian, - EdgeDetection.Prewitt, - EdgeDetection.RobertsCross, - EdgeDetection.Robinson, - EdgeDetection.Scharr, - EdgeDetection.Sobel - }; - - [Theory] - [MemberData(nameof(DetectEdgesFilters))] - public void ImageShouldApplyDetectEdgesFilter(EdgeDetection detector) - { - string path = this.CreateOutputDirectory("DetectEdges"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(detector); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.DetectEdges(detector).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(DetectEdgesFilters))] - public void ImageShouldApplyDetectEdgesFilterInBox(EdgeDetection detector) - { - string path = this.CreateOutputDirectory("DetectEdges"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(detector + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.DetectEdges(detector, new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file From d76fdedee731bbc584372dc2ef61adb28953d6df Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 15:22:12 +1000 Subject: [PATCH 51/84] Oilpainting --- .../Processing/Effects/OilPainting.cs | 33 +++++++++- .../Effects/OilPaintingProcessor.cs | 49 +++++--------- tests/ImageSharp.Tests/FileTestBase.cs | 24 +++++-- tests/ImageSharp.Tests/ImageComparer.cs | 37 ++++++----- .../Binarization/BinaryThresholdTest.cs | 4 +- .../Processing/Binarization/DitherTest.cs | 8 +-- .../Processing/ColorMatrix/BlackWhiteTest.cs | 4 +- .../ColorMatrix/ColorBlindnessTest.cs | 4 +- .../Processing/ColorMatrix/GrayscaleTest.cs | 4 +- .../Processing/ColorMatrix/HueTest.cs | 4 +- .../Processing/ColorMatrix/KodachromeTest.cs | 4 +- .../Processing/ColorMatrix/LomographTest.cs | 4 +- .../Processing/ColorMatrix/PolaroidTest.cs | 4 +- .../Processing/ColorMatrix/SaturationTest.cs | 4 +- .../Processing/ColorMatrix/SepiaTest.cs | 4 +- .../Processing/Convolution/BoxBlurTest.cs | 4 +- .../Processing/Convolution/DetectEdgesTest.cs | 4 +- .../Convolution/GaussianBlurTest.cs | 4 +- .../Convolution/GaussianSharpenTest.cs | 4 +- .../Processing/Effects/OilPaintTest.cs | 55 ++++++++++++++++ .../Processors/Filters/OilPaintTest.cs | 66 ------------------- .../TestUtilities/TestImageExtensions.cs | 4 +- 22 files changed, 175 insertions(+), 157 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs diff --git a/src/ImageSharp/Processing/Effects/OilPainting.cs b/src/ImageSharp/Processing/Effects/OilPainting.cs index d4528b55b..fd65542e0 100644 --- a/src/ImageSharp/Processing/Effects/OilPainting.cs +++ b/src/ImageSharp/Processing/Effects/OilPainting.cs @@ -16,6 +16,35 @@ namespace ImageSharp /// public static partial class ImageExtensions { + /// + /// Alters the colors of the image recreating an oil painting effect with levels and brushSize + /// set to 10 and 15 respectively. + /// + /// The pixel format. + /// The image this method extends. + /// The . + public static Image OilPaint(this Image source) + where TPixel : struct, IPixel + { + return OilPaint(source, 10, 15); + } + + /// + /// Alters the colors of the image recreating an oil painting effect with levels and brushSize + /// set to 10 and 15 respectively. + /// + /// The pixel format. + /// The image this method extends. + /// + /// The structure that specifies the portion of the image object to alter. + /// + /// The . + public static Image OilPaint(this Image source, Rectangle rectangle) + where TPixel : struct, IPixel + { + return OilPaint(source, 10, 15, rectangle); + } + /// /// Alters the colors of the image recreating an oil painting effect. /// @@ -24,8 +53,8 @@ namespace ImageSharp /// The number of intensity levels. Higher values result in a broader range of color intensities forming part of the result image. /// The number of neighboring pixels used in calculating each individual pixel value. /// The . - public static Image OilPaint(this Image source, int levels = 10, int brushSize = 15) - where TPixel : struct, IPixel + public static Image OilPaint(this Image source, int levels, int brushSize) + where TPixel : struct, IPixel { return OilPaint(source, levels, brushSize, source.Bounds); } diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs index a43f77a1c..37cc8a9d9 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs @@ -97,17 +97,7 @@ namespace ImageSharp.Processing.Processors int fyr = fy - radius; int offsetY = y + fyr; - // Skip the current row - if (offsetY < minY) - { - continue; - } - - // Outwith the current bounds so break. - if (offsetY >= maxY) - { - break; - } + offsetY = offsetY.Clamp(0, maxY); Span sourceOffsetRow = source.GetRowSpan(offsetY); @@ -115,34 +105,25 @@ namespace ImageSharp.Processing.Processors { int fxr = fx - radius; int offsetX = x + fxr; + offsetX = offsetX.Clamp(0, maxX); - // Skip the column - if (offsetX < 0) - { - continue; - } + var vector = sourceOffsetRow[offsetX].ToVector4(); - if (offsetX < maxX) - { - // ReSharper disable once AccessToDisposedClosure - var vector = sourceOffsetRow[offsetX].ToVector4(); + float sourceRed = vector.X; + float sourceBlue = vector.Z; + float sourceGreen = vector.Y; - float sourceRed = vector.X; - float sourceBlue = vector.Z; - float sourceGreen = vector.Y; + int currentIntensity = (int)MathF.Round((sourceBlue + sourceGreen + sourceRed) / 3F * (levels - 1)); - int currentIntensity = (int)MathF.Round((sourceBlue + sourceGreen + sourceRed) / 3F * (levels - 1)); + intensityBin[currentIntensity] += 1; + blueBin[currentIntensity] += sourceBlue; + greenBin[currentIntensity] += sourceGreen; + redBin[currentIntensity] += sourceRed; - intensityBin[currentIntensity] += 1; - blueBin[currentIntensity] += sourceBlue; - greenBin[currentIntensity] += sourceGreen; - redBin[currentIntensity] += sourceRed; - - if (intensityBin[currentIntensity] > maxIntensity) - { - maxIntensity = intensityBin[currentIntensity]; - maxIndex = currentIntensity; - } + if (intensityBin[currentIntensity] > maxIntensity) + { + maxIntensity = intensityBin[currentIntensity]; + maxIndex = currentIntensity; } } diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs index 654cdf64e..ff0801e8a 100644 --- a/tests/ImageSharp.Tests/FileTestBase.cs +++ b/tests/ImageSharp.Tests/FileTestBase.cs @@ -12,30 +12,42 @@ namespace ImageSharp.Tests /// public abstract class FileTestBase : TestBase { + /// + /// A collection made up of one file for each image format + /// + public static IEnumerable DefaultFiles = + new[] + { + TestImages.Bmp.Car, + TestImages.Jpeg.Baseline.Calliphora, + TestImages.Png.Splash, + TestImages.Gif.Trans + }; + /// /// A collection of all the bmp test images /// - public static IEnumerable AllBmpFiles => TestImages.Bmp.All; + public static IEnumerable AllBmpFiles = TestImages.Bmp.All; /// /// A collection of all the jpeg test images /// - public static IEnumerable AllJpegFiles => TestImages.Jpeg.All; + public static IEnumerable AllJpegFiles = TestImages.Jpeg.All; /// /// A collection of all the png test images /// - public static IEnumerable AllPngFiles => TestImages.Png.All; + public static IEnumerable AllPngFiles = TestImages.Png.All; /// /// A collection of all the gif test images /// - public static IEnumerable AllGifFiles => TestImages.Gif.All; + public static IEnumerable AllGifFiles = TestImages.Gif.All; /// - /// The standard pixel formats enumerations + /// The standard pixel format enumeration /// - public const PixelTypes StandardPixelTypes = PixelTypes.StandardImageClass | PixelTypes.Rgba32; + public const PixelTypes StandardPixelType = PixelTypes.StandardImageClass; public static class Extensions { diff --git a/tests/ImageSharp.Tests/ImageComparer.cs b/tests/ImageSharp.Tests/ImageComparer.cs index d339dc83d..3e40cc2d7 100644 --- a/tests/ImageSharp.Tests/ImageComparer.cs +++ b/tests/ImageSharp.Tests/ImageComparer.cs @@ -1,4 +1,9 @@ -namespace ImageSharp.Tests +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests { using System; using ImageSharp; @@ -12,9 +17,9 @@ /// public static class ImageComparer { - const int DefaultScalingFactor = 32; // this is means the images get scaled into a 32x32 image to sample pixels - const int DefaultSegmentThreshold = 3; // the greyscale difference between 2 segements my be > 3 before it influances the overall difference - const float DefaultImageThreshold = 0.000f; // after segment threasholds the images must have no differences + const int DefaultScalingFactor = 32; // This is means the images get scaled into a 32x32 image to sample pixels + const int DefaultSegmentThreshold = 3; // The greyscale difference between 2 segements my be > 3 before it influences the overall difference + const float DefaultImageThreshold = 0.000F; // After segment thresholds the images must have no differences /// /// Does a visual comparison between 2 images and then asserts the difference is less then a configurable threshold @@ -25,15 +30,15 @@ /// The actual image /// /// The threshold for the percentage difference where the images are asumed to be the same. - /// The default/undefined value is + /// The default/undefined value is /// /// - /// The threashold of the individual segments before it acumulates towards the overall difference. - /// The default undefined value is + /// The threshold of the individual segments before it acumulates towards the overall difference. + /// The default undefined value is /// /// /// This is a sampling factor we sample a grid of average pixels width by high - /// The default undefined value is + /// The default undefined value is /// public static void CheckSimilarity(Image expected, Image actual, float imageTheshold = DefaultImageThreshold, byte segmentThreshold = DefaultSegmentThreshold, int scalingFactor = DefaultScalingFactor) where TPixelA : struct, IPixel @@ -52,8 +57,8 @@ /// The source image /// The target image /// - /// The threashold of the individual segments before it acumulates towards the overall difference. - /// The default undefined value is + /// The threshold of the individual segments before it acumulates towards the overall difference. + /// The default undefined value is /// /// /// This is a sampling factor we sample a grid of average pixels width by high @@ -74,14 +79,14 @@ if (b > segmentThreshold) { diffPixels++; } } - return (float)diffPixels / (float)(scalingFactor * scalingFactor); + return diffPixels / (float)(scalingFactor * scalingFactor); } private static Fast2DArray GetDifferences(Image source, Image target, int scalingFactor) where TPixelA : struct, IPixel where TPixelB : struct, IPixel { - Fast2DArray differences = new Fast2DArray(scalingFactor, scalingFactor); + var differences = new Fast2DArray(scalingFactor, scalingFactor); Fast2DArray firstGray = source.GetGrayScaleValues(scalingFactor); Fast2DArray secondGray = target.GetGrayScaleValues(scalingFactor); @@ -89,7 +94,7 @@ { for (int x = 0; x < scalingFactor; x++) { - var diff = firstGray[x, y] - secondGray[x, y]; + int diff = firstGray[x, y] - secondGray[x, y]; differences[x, y] = (byte)Math.Abs(diff); } } @@ -100,18 +105,18 @@ private static Fast2DArray GetGrayScaleValues(this Image source, int scalingFactor) where TPixelA : struct, IPixel { - byte[] buffer = new byte[4]; + byte[] buffer = new byte[3]; using (Image img = new Image(source).Resize(scalingFactor, scalingFactor).Grayscale()) { using (PixelAccessor pixels = img.Lock()) { - Fast2DArray grayScale = new Fast2DArray(scalingFactor, scalingFactor); + var grayScale = new Fast2DArray(scalingFactor, scalingFactor); for (int y = 0; y < scalingFactor; y++) { for (int x = 0; x < scalingFactor; x++) { pixels[x, y].ToXyzBytes(buffer, 0); - grayScale[x, y] = buffer[1]; + grayScale[x, y] = buffer[0]; } } diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs index 7286375ba..a4da02ade 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Binarization }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(BinaryThresholdValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(BinaryThresholdValues), StandardPixelType)] public void ImageShouldApplyBinaryThresholdFilter(TestImageProvider provider, float value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Binarization } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(BinaryThresholdValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(BinaryThresholdValues), StandardPixelType)] public void ImageShouldApplyBinaryThresholdInBox(TestImageProvider provider, float value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs index c88227b2c..a6585e026 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs @@ -32,7 +32,7 @@ namespace ImageSharp.Tests }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(Ditherers), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(Ditherers), StandardPixelType)] public void ImageShouldApplyDitherFilter(TestImageProvider provider, string name, IOrderedDither ditherer) where TPixel : struct, IPixel { @@ -44,7 +44,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(Ditherers), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(Ditherers), StandardPixelType)] public void ImageShouldApplyDitherFilterInBox(TestImageProvider provider, string name, IOrderedDither ditherer) where TPixel : struct, IPixel { @@ -64,7 +64,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(ErrorDiffusers), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(ErrorDiffusers), StandardPixelType)] public void ImageShouldApplyDiffusionFilter(TestImageProvider provider, string name, IErrorDiffuser diffuser) where TPixel : struct, IPixel { @@ -76,7 +76,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(ErrorDiffusers), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(ErrorDiffusers), StandardPixelType)] public void ImageShouldApplyDiffusionFilterInBox(TestImageProvider provider, string name, IErrorDiffuser diffuser) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs index e3083cbe1..97582b27f 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class BlackWhiteTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplyBlackWhiteFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplyBlackWhiteFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs index 24df04fdf..7c6e58da3 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs @@ -26,7 +26,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(ColorBlindnessFilters), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(ColorBlindnessFilters), StandardPixelType)] public void ImageShouldApplyColorBlindnessFilter(TestImageProvider provider, ColorBlindness colorBlindness) where TPixel : struct, IPixel { @@ -38,7 +38,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(ColorBlindnessFilters), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(ColorBlindnessFilters), StandardPixelType)] public void ImageShouldApplyColorBlindnessFilterInBox(TestImageProvider provider, ColorBlindness colorBlindness) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs index c68b7c5c3..f0a23429d 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs @@ -23,7 +23,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix /// Use test patterns over loaded images to save decode time. /// [Theory] - [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, StandardPixelTypes)] + [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, StandardPixelType)] public void ImageShouldApplyGrayscaleFilterAll(TestImageProvider provider, GrayscaleMode value) where TPixel : struct, IPixel { @@ -43,7 +43,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, StandardPixelTypes)] + [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, StandardPixelType)] public void ImageShouldApplyGrayscaleFilterInBox(TestImageProvider provider, GrayscaleMode value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs index 9b6510631..0666d505a 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(HueValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(HueValues), StandardPixelType)] public void ImageShouldApplyHueFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(HueValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(HueValues), StandardPixelType)] public void ImageShouldApplyHueFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs index ece3eb41a..23fd634e2 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class KodachromeTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplyKodachromeFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplyKodachromeFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs index 2ea686fd9..b0af0e6c3 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs @@ -14,7 +14,7 @@ namespace ImageSharp.Tests public class LomographTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplyLomographFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -26,7 +26,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplyLomographFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs index 1803fb581..ff6640753 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class PolaroidTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplyPolaroidFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplyPolaroidFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs index 506f29503..924b9d5d4 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(SaturationValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(SaturationValues), StandardPixelType)] public void ImageShouldApplySaturationFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(SaturationValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(SaturationValues), StandardPixelType)] public void ImageShouldApplySaturationFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs index b129ffe56..cd5baa1ce 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class SepiaTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplySepiaFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] public void ImageShouldApplySepiaFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs index f19e6cd0c..9e276fcb3 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(BoxBlurValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(BoxBlurValues), StandardPixelType)] public void ImageShouldApplyBoxBlurFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(BoxBlurValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(BoxBlurValues), StandardPixelType)] public void ImageShouldApplyBoxBlurFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs index 4e5a230ec..3155a9956 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs @@ -28,7 +28,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(DetectEdgesFilters), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(DetectEdgesFilters), StandardPixelType)] public void ImageShouldApplyDetectEdgesFilter(TestImageProvider provider, EdgeDetection detector) where TPixel : struct, IPixel { @@ -40,7 +40,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(DetectEdgesFilters), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(DetectEdgesFilters), StandardPixelType)] public void ImageShouldApplyDetectEdgesFilterInBox(TestImageProvider provider, EdgeDetection detector) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs index d80daf1d6..8bdc588be 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianBlurValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianBlurValues), StandardPixelType)] public void ImageShouldApplyGaussianBlurFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianBlurValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianBlurValues), StandardPixelType)] public void ImageShouldApplyGaussianBlurFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs index 1632e2c2f..0497459d7 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianSharpenValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianSharpenValues), StandardPixelType)] public void ImageShouldApplyGaussianSharpenFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianSharpenValues), StandardPixelTypes)] + [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianSharpenValues), StandardPixelType)] public void ImageShouldApplyGaussianSharpenFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs b/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs new file mode 100644 index 000000000..3d4725f88 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs @@ -0,0 +1,55 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class OilPaintTest : FileTestBase + { + public static readonly TheoryData OilPaintValues + = new TheoryData + { + { 15, 10 }, + { 6, 5 } + }; + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), StandardPixelType)] + public void ImageShouldApplyOilPaintFilter(TestImageProvider provider, int levels, int brushSize) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.OilPaint(levels, brushSize) + .DebugSave(provider, string.Join("-", levels, brushSize), Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), StandardPixelType)] + public void ImageShouldApplyOilPaintFilterInBox(TestImageProvider provider, int levels, int brushSize) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.OilPaint(levels, brushSize, bounds) + .DebugSave(provider, string.Join("-", levels, brushSize), Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + + // TODO: Why does the png box fail without the additional parameter. + ImageComparer.CheckSimilarity(source, image, 0.001F); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs b/tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs deleted file mode 100644 index 5facee346..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System; - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class OilPaintTest : FileTestBase - { - public static readonly TheoryData> OilPaintValues - = new TheoryData> - { - new Tuple(15, 10), - new Tuple(6, 5) - }; - - [Theory] - [MemberData(nameof(OilPaintValues))] - public void ImageShouldApplyOilPaintFilter(Tuple value) - { - string path = this.CreateOutputDirectory("OilPaint"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - if (image.Width > value.Item2 && image.Height > value.Item2) - { - image.OilPaint(value.Item1, value.Item2).Save(output); - } - } - } - } - - [Theory] - [MemberData(nameof(OilPaintValues))] - public void ImageShouldApplyOilPaintFilterInBox(Tuple value) - { - string path = this.CreateOutputDirectory("OilPaint"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - using (Image image = file.CreateImage()) - { - if (image.Width > value.Item2 && image.Height > value.Item2) - { - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.OilPaint(value.Item1, value.Item2, new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index f55cfbf16..d31150a92 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -40,7 +40,9 @@ namespace ImageSharp.Tests } else if (settings != null) { - if (settings.GetType().GetTypeInfo().IsPrimitive) + Type type = settings.GetType(); + TypeInfo info = type.GetTypeInfo(); + if (info.IsPrimitive || info.IsEnum || type == typeof(decimal)) { tag = settings.ToString(); } From 78a9e9e0b883fdca9c0fe49d8819000452ad49f1 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 15:55:11 +1000 Subject: [PATCH 52/84] Alpha --- .../Processing/Effects/AlphaTest.cs | 53 +++++++++++++++++ .../Processors/Filters/AlphaTest.cs | 57 ------------------- 2 files changed, 53 insertions(+), 57 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs diff --git a/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs b/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs new file mode 100644 index 000000000..a25e48ac3 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Effects +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class AlphaTest : FileTestBase + { + public static readonly TheoryData AlphaValues + = new TheoryData + { + 20/100F, + 80/100F + }; + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(AlphaValues), StandardPixelType)] + public void ImageShouldApplyAlphaFilter(TestImageProvider provider, float value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Alpha(value) + .DebugSave(provider, value, Extensions.Png); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(AlphaValues), StandardPixelType)] + public void ImageShouldApplyAlphaFilterInBox(TestImageProvider provider, float value) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Alpha(value, bounds) + .DebugSave(provider, value, Extensions.Png); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs b/tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs deleted file mode 100644 index 401ac916b..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/AlphaTest.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class AlphaTest : FileTestBase - { - public static readonly TheoryData AlphaValues - = new TheoryData - { - 20/100f , - 80/100f - }; - - [Theory] - [MemberData(nameof(AlphaValues))] - public void ImageShouldApplyAlphaFilter(float value) - { - string path = this.CreateOutputDirectory("Alpha"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Alpha(value).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(AlphaValues))] - public void ImageShouldApplyAlphaFilterInBox(float value) - { - string path = this.CreateOutputDirectory("Alpha"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Alpha(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From 1e4108824998553bf2e118489c48b42dbbd24288 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 15:56:55 +1000 Subject: [PATCH 53/84] Use default files. --- .../Processing/Binarization/BinaryThresholdTest.cs | 4 ++-- .../Processing/Binarization/DitherTest.cs | 8 ++++---- .../Processing/ColorMatrix/BlackWhiteTest.cs | 4 ++-- .../Processing/ColorMatrix/ColorBlindnessTest.cs | 4 ++-- .../Processing/ColorMatrix/KodachromeTest.cs | 4 ++-- .../Processing/ColorMatrix/LomographTest.cs | 4 ++-- .../Processing/ColorMatrix/PolaroidTest.cs | 4 ++-- .../Processing/ColorMatrix/SaturationTest.cs | 4 ++-- .../ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs | 4 ++-- .../Processing/Convolution/BoxBlurTest.cs | 4 ++-- .../Processing/Convolution/DetectEdgesTest.cs | 4 ++-- .../Processing/Convolution/GaussianBlurTest.cs | 4 ++-- .../Processing/Convolution/GaussianSharpenTest.cs | 4 ++-- 13 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs index a4da02ade..967844004 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Binarization }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(BinaryThresholdValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), StandardPixelType)] public void ImageShouldApplyBinaryThresholdFilter(TestImageProvider provider, float value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Binarization } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(BinaryThresholdValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), StandardPixelType)] public void ImageShouldApplyBinaryThresholdInBox(TestImageProvider provider, float value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs index a6585e026..92f685dfa 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs @@ -32,7 +32,7 @@ namespace ImageSharp.Tests }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(Ditherers), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(Ditherers), StandardPixelType)] public void ImageShouldApplyDitherFilter(TestImageProvider provider, string name, IOrderedDither ditherer) where TPixel : struct, IPixel { @@ -44,7 +44,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(Ditherers), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(Ditherers), StandardPixelType)] public void ImageShouldApplyDitherFilterInBox(TestImageProvider provider, string name, IOrderedDither ditherer) where TPixel : struct, IPixel { @@ -64,7 +64,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(ErrorDiffusers), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ErrorDiffusers), StandardPixelType)] public void ImageShouldApplyDiffusionFilter(TestImageProvider provider, string name, IErrorDiffuser diffuser) where TPixel : struct, IPixel { @@ -76,7 +76,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(ErrorDiffusers), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ErrorDiffusers), StandardPixelType)] public void ImageShouldApplyDiffusionFilterInBox(TestImageProvider provider, string name, IErrorDiffuser diffuser) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs index 97582b27f..066b392d7 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class BlackWhiteTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplyBlackWhiteFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplyBlackWhiteFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs index 7c6e58da3..314b405c2 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs @@ -26,7 +26,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(ColorBlindnessFilters), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ColorBlindnessFilters), StandardPixelType)] public void ImageShouldApplyColorBlindnessFilter(TestImageProvider provider, ColorBlindness colorBlindness) where TPixel : struct, IPixel { @@ -38,7 +38,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(ColorBlindnessFilters), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ColorBlindnessFilters), StandardPixelType)] public void ImageShouldApplyColorBlindnessFilterInBox(TestImageProvider provider, ColorBlindness colorBlindness) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs index 23fd634e2..2824d8fd2 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class KodachromeTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplyKodachromeFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplyKodachromeFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs index b0af0e6c3..146af1652 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs @@ -14,7 +14,7 @@ namespace ImageSharp.Tests public class LomographTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplyLomographFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -26,7 +26,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplyLomographFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs index ff6640753..4304f3b45 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class PolaroidTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplyPolaroidFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplyPolaroidFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs index 924b9d5d4..fcc9656f3 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(SaturationValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(SaturationValues), StandardPixelType)] public void ImageShouldApplySaturationFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(SaturationValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(SaturationValues), StandardPixelType)] public void ImageShouldApplySaturationFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs index cd5baa1ce..47eaa874e 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class SepiaTest : FileTestBase { [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplySepiaFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] public void ImageShouldApplySepiaFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs index 9e276fcb3..e171dca99 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(BoxBlurValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), StandardPixelType)] public void ImageShouldApplyBoxBlurFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(BoxBlurValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), StandardPixelType)] public void ImageShouldApplyBoxBlurFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs index 3155a9956..b03afdb22 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs @@ -28,7 +28,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(DetectEdgesFilters), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(DetectEdgesFilters), StandardPixelType)] public void ImageShouldApplyDetectEdgesFilter(TestImageProvider provider, EdgeDetection detector) where TPixel : struct, IPixel { @@ -40,7 +40,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(DetectEdgesFilters), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(DetectEdgesFilters), StandardPixelType)] public void ImageShouldApplyDetectEdgesFilterInBox(TestImageProvider provider, EdgeDetection detector) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs index 8bdc588be..d91e4089e 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianBlurValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), StandardPixelType)] public void ImageShouldApplyGaussianBlurFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianBlurValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), StandardPixelType)] public void ImageShouldApplyGaussianBlurFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs index 0497459d7..30bb44a67 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianSharpenValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), StandardPixelType)] public void ImageShouldApplyGaussianSharpenFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(GaussianSharpenValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), StandardPixelType)] public void ImageShouldApplyGaussianSharpenFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { From c99bbe586dcebaf1cc7b93ee8baa4995daeff7c3 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 15:57:19 +1000 Subject: [PATCH 54/84] Update Hue --- tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs index 0666d505a..a102adb92 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(HueValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(HueValues), StandardPixelType)] public void ImageShouldApplyHueFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(AllBmpFiles), nameof(HueValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(HueValues), StandardPixelType)] public void ImageShouldApplyHueFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { From a8a4dc057ce04416b8d7e82515aa09e063e236a6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 16:09:53 +1000 Subject: [PATCH 55/84] BackgroundColor --- .../Processing/Effects/BackgroundColorTest.cs | 46 ++++++++++++++++++ .../Processors/Filters/BackgroundColorTest.cs | 47 ------------------- 2 files changed, 46 insertions(+), 47 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/BackgroundColorTest.cs diff --git a/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs b/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs new file mode 100644 index 000000000..fd56dd6e7 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Effects +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class BackgroundColorTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyBackgroundColorFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.BackgroundColor(NamedColors.HotPink) + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyBackgroundColorFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.BackgroundColor(NamedColors.HotPink, bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/BackgroundColorTest.cs b/tests/ImageSharp.Tests/Processors/Filters/BackgroundColorTest.cs deleted file mode 100644 index d7ca78d1b..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/BackgroundColorTest.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class BackgroundColorTest : FileTestBase - { - [Fact] - public void ImageShouldApplyBackgroundColorFilter() - { - string path = this.CreateOutputDirectory("BackgroundColor"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.BackgroundColor(Rgba32.HotPink).Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyBackgroundColorFilterInBox() - { - string path = this.CreateOutputDirectory("BackgroundColor"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.BackgroundColor(Rgba32.HotPink, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From abab7df1e4b5b8cbafae1541d6706440d77fc9f8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 16:17:41 +1000 Subject: [PATCH 56/84] Brightness, Contrast --- .../Processing/Effects/BrightnessTest.cs | 53 +++++++++++++++++ .../Processing/Effects/ContrastTest.cs | 53 +++++++++++++++++ .../Processors/Filters/BrightnessTest.cs | 57 ------------------- .../Processors/Filters/ContrastTest.cs | 56 ------------------ 4 files changed, 106 insertions(+), 113 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/BrightnessTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/ContrastTest.cs diff --git a/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs b/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs new file mode 100644 index 000000000..38c374635 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Effects +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class BrightnessTest : FileTestBase + { + public static readonly TheoryData BrightnessValues + = new TheoryData + { + 50, + -50 + }; + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(BrightnessValues), StandardPixelType)] + public void ImageShouldApplyBrightnessFilter(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Brightness(value) + .DebugSave(provider, value, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(BrightnessValues), StandardPixelType)] + public void ImageShouldApplyBrightnessFilterInBox(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Brightness(value, bounds) + .DebugSave(provider, value, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs b/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs new file mode 100644 index 000000000..837cf8057 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Effects +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class ContrastTest : FileTestBase + { + public static readonly TheoryData ContrastValues + = new TheoryData + { + 50, + -50 + }; + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(ContrastValues), StandardPixelType)] + public void ImageShouldApplyContrastFilter(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Contrast(value) + .DebugSave(provider, value, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(ContrastValues), StandardPixelType)] + public void ImageShouldApplyContrastFilterInBox(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Contrast(value, bounds) + .DebugSave(provider, value, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/BrightnessTest.cs b/tests/ImageSharp.Tests/Processors/Filters/BrightnessTest.cs deleted file mode 100644 index ce434d734..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/BrightnessTest.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class BrightnessTest : FileTestBase - { - public static readonly TheoryData BrightnessValues - = new TheoryData - { - 50 , - -50 , - }; - - [Theory] - [MemberData(nameof(BrightnessValues))] - public void ImageShouldApplyBrightnessFilter(int value) - { - string path = this.CreateOutputDirectory("Brightness"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Brightness(value).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(BrightnessValues))] - public void ImageShouldApplyBrightnessFilterInBox(int value) - { - string path = this.CreateOutputDirectory("Brightness"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Brightness(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/ContrastTest.cs b/tests/ImageSharp.Tests/Processors/Filters/ContrastTest.cs deleted file mode 100644 index 4626fbb6e..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/ContrastTest.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class ContrastTest : FileTestBase - { - public static readonly TheoryData ContrastValues - = new TheoryData - { - 50 , - -50 , - }; - - [Theory] - [MemberData(nameof(ContrastValues))] - public void ImageShouldApplyContrastFilter(int value) - { - string path = this.CreateOutputDirectory("Contrast"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Contrast(value).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ContrastValues))] - public void ImageShouldApplyContrastFilterInBox(int value) - { - string path = this.CreateOutputDirectory("Contrast"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value + "-InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Contrast(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file From f10fb06a64b3166a2895cab2ae8c18ea1e754b68 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 16:29:35 +1000 Subject: [PATCH 57/84] Invert, Pixelate --- .../Processing/Effects/InvertTest.cs | 46 +++++++++ .../Processing/Effects/PixelateTest.cs | 82 ++++++++++++++++ .../Processors/Filters/InvertTest.cs | 46 --------- .../Processors/Filters/PixelateTest.cs | 94 ------------------- 4 files changed, 128 insertions(+), 140 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/InvertTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs diff --git a/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs b/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs new file mode 100644 index 000000000..af2ac1edb --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs @@ -0,0 +1,46 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Effects +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class InvertTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyInvertFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Invert() + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyInvertFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Invert(bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs b/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs new file mode 100644 index 000000000..d52b7a290 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs @@ -0,0 +1,82 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Effects +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class PixelateTest : FileTestBase + { + public static readonly TheoryData PixelateValues + = new TheoryData + { + 4 , + 8 + }; + + [Theory] + [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.StandardImageClass)] + public void ImageShouldApplyPixelateFilter(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Pixelate(value) + .DebugSave(provider, value, Extensions.Bmp); + + // Test the neigbouring pixels + for (int y = 0; y < image.Height; y += value) + { + for (int x = 0; x < image.Width; x += value) + { + TPixel source = image[x, y]; + for (int pixY = y; pixY < y + value && pixY < image.Height; pixY++) + { + for (int pixX = x; pixX < x + value && pixX < image.Width; pixX++) + { + Assert.Equal(source, image[pixX, pixY]); + } + } + } + } + } + } + + [Theory] + [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.StandardImageClass)] + public void ImageShouldApplyPixelateFilterInBox(TestImageProvider provider, int value) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); + + image.Pixelate(value, bounds) + .DebugSave(provider, value, Extensions.Bmp); + + for (int y = 0; y < image.Height; y++) + { + for (int x = 0; x < image.Width; x++) + { + int tx = x; + int ty = y; + TPixel sourceColor = source[tx, ty]; + if (bounds.Contains(tx, ty)) + { + int sourceX = tx - ((tx - bounds.Left) % value) + (value / 2); + int sourceY = ty - ((ty - bounds.Top) % value) + (value / 2); + + sourceColor = image[sourceX, sourceY]; + } + Assert.Equal(sourceColor, image[tx, ty]); + } + } + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/InvertTest.cs b/tests/ImageSharp.Tests/Processors/Filters/InvertTest.cs deleted file mode 100644 index 6d375d09a..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/InvertTest.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class InvertTest : FileTestBase - { - [Fact] - public void ImageShouldApplyInvertFilter() - { - string path = this.CreateOutputDirectory("Invert"); - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Invert().Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyInvertFilterInBox() - { - string path = this.CreateOutputDirectory("Invert"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Invert(new Rectangle(10, 10, image.Width / 2, image.Height / 2)).Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs b/tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs deleted file mode 100644 index b21a8c969..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - using ImageSharp.PixelFormats; - using Xunit; - - public class PixelateTest - { - public static readonly TheoryData PixelateValues - = new TheoryData - { - 4 , - 8 - }; - - [Theory] - [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.StandardImageClass)] - public void ImageShouldApplyPixelateFilter(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image image = provider.GetImage()) - { - image.Pixelate(value) - .DebugSave(provider, new - { - size = value - }); - - using (PixelAccessor pixels = image.Lock()) - { - for (int y = 0; y < pixels.Height; y += value) - { - for (int x = 0; x < pixels.Width; x += value) - { - TPixel source = pixels[x, y]; - for (int pixY = y; pixY < y + value && pixY < pixels.Height; pixY++) - { - for (int pixX = x; pixX < x + value && pixX < pixels.Width; pixX++) - { - Assert.Equal(source, pixels[pixX, pixY]); - } - } - } - } - } - } - } - - [Theory] - [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.StandardImageClass)] - public void ImageShouldApplyPixelateFilterInBox(TestImageProvider provider, int value) - where TPixel : struct, IPixel - { - using (Image source = provider.GetImage()) - using (Image image = new Image(source)) - { - Rectangle rect = new Rectangle(image.Width/4, image.Height / 4, image.Width / 2, image.Height / 2); - - image.Pixelate(value, rect) - .DebugSave(provider, new - { - size = value - }); - - using (PixelAccessor pixels = image.Lock()) - using (PixelAccessor sourcePixels = source.Lock()) - { - for (int y = 0; y < pixels.Height; y++) - { - for (int x = 0; x < pixels.Width; x++) - { - var tx = x; - var ty = y; - TPixel sourceColor = sourcePixels[tx, ty]; - if (rect.Contains(tx, ty)) - { - var sourceX = tx - ((tx - rect.Left) % value) + (value / 2); - var sourceY = ty - ((ty - rect.Top) % value) + (value / 2); - - sourceColor = pixels[sourceX, sourceY]; - } - Assert.Equal(sourceColor, pixels[tx, ty]); - } - } - } - } - } - } -} \ No newline at end of file From 88282ba54e79c61f268e711a73494309b7af3fd8 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 16:43:09 +1000 Subject: [PATCH 58/84] Glow, Vignette --- src/ImageSharp/Processing/Overlays/Glow.cs | 4 +- .../Processing/Overlays/Vignette.cs | 4 +- .../Processing/Overlays/GlowTest.cs | 70 ++++++++++++++++ .../Processing/Overlays/VignetteTest.cs | 70 ++++++++++++++++ .../Processors/Filters/GlowTest.cs | 80 ------------------- .../Processors/Filters/VignetteTest.cs | 80 ------------------- 6 files changed, 142 insertions(+), 166 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs create mode 100644 tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/GlowTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/VignetteTest.cs diff --git a/src/ImageSharp/Processing/Overlays/Glow.cs b/src/ImageSharp/Processing/Overlays/Glow.cs index 587bbe610..04c85e00c 100644 --- a/src/ImageSharp/Processing/Overlays/Glow.cs +++ b/src/ImageSharp/Processing/Overlays/Glow.cs @@ -5,8 +5,6 @@ namespace ImageSharp { - using System; - using ImageSharp.PixelFormats; using Processing.Processors; @@ -158,7 +156,7 @@ namespace ImageSharp public static Image Glow(this Image source, TPixel color, float radius, Rectangle rectangle, GraphicsOptions options) where TPixel : struct, IPixel { - GlowProcessor processor = new GlowProcessor(color, options) { Radius = radius, }; + var processor = new GlowProcessor(color, options) { Radius = radius, }; source.ApplyProcessor(processor, rectangle); return source; } diff --git a/src/ImageSharp/Processing/Overlays/Vignette.cs b/src/ImageSharp/Processing/Overlays/Vignette.cs index 2eaf2e1ef..c04e88718 100644 --- a/src/ImageSharp/Processing/Overlays/Vignette.cs +++ b/src/ImageSharp/Processing/Overlays/Vignette.cs @@ -5,8 +5,6 @@ namespace ImageSharp { - using System; - using ImageSharp.PixelFormats; using Processing.Processors; @@ -162,7 +160,7 @@ namespace ImageSharp public static Image Vignette(this Image source, TPixel color, float radiusX, float radiusY, Rectangle rectangle, GraphicsOptions options) where TPixel : struct, IPixel { - VignetteProcessor processor = new VignetteProcessor(color, options) { RadiusX = radiusX, RadiusY = radiusY }; + var processor = new VignetteProcessor(color, options) { RadiusX = radiusX, RadiusY = radiusY }; source.ApplyProcessor(processor, rectangle); return source; } diff --git a/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs b/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs new file mode 100644 index 000000000..0a94659bb --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs @@ -0,0 +1,70 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Overlays +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class GlowTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyGlowFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Glow() + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyGlowFilterColor(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Glow(NamedColors.Orange) + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyGlowFilterRadius(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Glow(image.Width / 4F) + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyGlowFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Glow(bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs b/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs new file mode 100644 index 000000000..7a566a1b3 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs @@ -0,0 +1,70 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Overlays +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class VignetteTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyVignetteFilter(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Vignette() + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyVignetteFilterColor(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Vignette(NamedColors.Orange) + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyVignetteFilterRadius(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Vignette(image.Width / 4F, image.Height / 4F) + .DebugSave(provider, null, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldApplyVignetteFilterInBox(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image source = provider.GetImage()) + using (var image = new Image(source)) + { + var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + + image.Vignette(bounds) + .DebugSave(provider, null, Extensions.Bmp); + + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + image.Fill(NamedColors.HotPink, bounds); + source.Fill(NamedColors.HotPink, bounds); + ImageComparer.CheckSimilarity(image, source); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/GlowTest.cs b/tests/ImageSharp.Tests/Processors/Filters/GlowTest.cs deleted file mode 100644 index 43e45f9ca..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/GlowTest.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class GlowTest : FileTestBase - { - [Fact] - public void ImageShouldApplyGlowFilter() - { - string path = this.CreateOutputDirectory("Glow"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Glow().Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyGlowFilterColor() - { - string path = this.CreateOutputDirectory("Glow"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("Color"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Glow(Rgba32.HotPink).Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyGlowFilterRadius() - { - string path = this.CreateOutputDirectory("Glow"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("Radius"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Glow(image.Width / 4F).Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyGlowFilterInBox() - { - string path = this.CreateOutputDirectory("Glow"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Glow(new Rectangle(image.Width / 8, image.Height / 8, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/VignetteTest.cs b/tests/ImageSharp.Tests/Processors/Filters/VignetteTest.cs deleted file mode 100644 index 4191ae8fa..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/VignetteTest.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class VignetteTest : FileTestBase - { - [Fact] - public void ImageShouldApplyVignetteFilter() - { - string path = this.CreateOutputDirectory("Vignette"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Vignette().Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyVignetteFilterColor() - { - string path = this.CreateOutputDirectory("Vignette"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("Color"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Vignette(Rgba32.HotPink).Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyVignetteFilterRadius() - { - string path = this.CreateOutputDirectory("Vignette"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("Radius"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Vignette(image.Width / 4F, image.Height / 4F).Save(output); - } - } - } - - [Fact] - public void ImageShouldApplyVignetteFilterInBox() - { - string path = this.CreateOutputDirectory("Vignette"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName("InBox"); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Vignette(new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2)) - .Save(output); - } - } - } - } -} \ No newline at end of file From 72fb7b4f46ba594f8eca9662315f0d3e29e383f9 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 17:08:06 +1000 Subject: [PATCH 59/84] AutoOrient --- .../Processing/Transforms/AutoOrient.cs | 4 +-- .../Transforms}/AutoOrientTests.cs | 28 ++++++++----------- .../TestUtilities/TestImageExtensions.cs | 5 ++-- 3 files changed, 16 insertions(+), 21 deletions(-) rename tests/ImageSharp.Tests/{Processors/Filters => Processing/Transforms}/AutoOrientTests.cs (64%) diff --git a/src/ImageSharp/Processing/Transforms/AutoOrient.cs b/src/ImageSharp/Processing/Transforms/AutoOrient.cs index b892db41a..51948c1a7 100644 --- a/src/ImageSharp/Processing/Transforms/AutoOrient.cs +++ b/src/ImageSharp/Processing/Transforms/AutoOrient.cs @@ -5,12 +5,10 @@ namespace ImageSharp { - using System; using ImageSharp.PixelFormats; using ImageSharp.Processing; - using Processing.Processors; /// /// Extension methods for the type. @@ -80,7 +78,7 @@ namespace ImageSharp return Orientation.Unknown; } - Orientation orientation = (Orientation)value.Value; + var orientation = (Orientation)value.Value; source.MetaData.ExifProfile.SetValue(ExifTag.Orientation, (ushort)Orientation.TopLeft); diff --git a/tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs similarity index 64% rename from tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs rename to tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs index d31a7468f..bae1b8332 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs @@ -3,17 +3,17 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp.Tests +namespace ImageSharp.Tests.Processing.Transforms { - using System.IO; - using ImageSharp.PixelFormats; - using ImageSharp.Processing; + using Xunit; public class AutoOrientTests : FileTestBase { + public static readonly string[] FlipFiles = { TestImages.Bmp.F }; + public static readonly TheoryData OrientationValues = new TheoryData { @@ -29,23 +29,19 @@ namespace ImageSharp.Tests }; [Theory] - [MemberData(nameof(OrientationValues))] - public void ImageShouldFlip(RotateType rotateType, FlipType flipType, ushort orientation) + [WithFileCollection(nameof(FlipFiles), nameof(OrientationValues), StandardPixelType)] + public void ImageShouldAutoRotate(TestImageProvider provider, RotateType rotateType, FlipType flipType, ushort orientation) + where TPixel : struct, IPixel { - string path = this.CreateOutputDirectory("AutoOrient"); - - TestFile file = TestFile.Create(TestImages.Bmp.F); - - using (Image image = file.CreateImage()) + using (Image image = provider.GetImage()) { image.MetaData.ExifProfile = new ExifProfile(); image.MetaData.ExifProfile.SetValue(ExifTag.Orientation, orientation); - using (FileStream before = File.OpenWrite($"{path}/before-{file.FileName}")) - using (FileStream after = File.OpenWrite($"{path}/after-{file.FileName}")) - { - image.RotateFlip(rotateType, flipType).Save(before).AutoOrient().Save(after); - } + image.RotateFlip(rotateType, flipType) + .DebugSave(provider, "before", Extensions.Bmp) + .AutoOrient() + .DebugSave(provider, "after", Extensions.Bmp); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index d31150a92..bb97daaa4 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -22,12 +22,12 @@ namespace ImageSharp.Tests /// The image provider /// The settings /// The extension - public static void DebugSave(this Image image, ITestImageProvider provider, object settings = null, string extension = "png") + public static Image DebugSave(this Image image, ITestImageProvider provider, object settings = null, string extension = "png") where TPixel : struct, IPixel { if (bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) && isCi) { - return; + return image; } // We are running locally then we want to save it out @@ -55,6 +55,7 @@ namespace ImageSharp.Tests } provider.Utility.SaveTestOutputFile(image, extension, tag: tag); + return image; } } } From d3b0d046d0d10605c5e389947243e64279a783d6 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 17:13:08 +1000 Subject: [PATCH 60/84] Crop --- .../Processing/Transforms/AutoOrient.cs | 1 - .../Processing/Transforms/CropTest.cs | 26 ++++++++++++++++ .../Processors/Filters/CropTest.cs | 31 ------------------- 3 files changed, 26 insertions(+), 32 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/CropTest.cs diff --git a/src/ImageSharp/Processing/Transforms/AutoOrient.cs b/src/ImageSharp/Processing/Transforms/AutoOrient.cs index 51948c1a7..07e5d5bc9 100644 --- a/src/ImageSharp/Processing/Transforms/AutoOrient.cs +++ b/src/ImageSharp/Processing/Transforms/AutoOrient.cs @@ -5,7 +5,6 @@ namespace ImageSharp { - using ImageSharp.PixelFormats; using ImageSharp.Processing; diff --git a/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs new file mode 100644 index 000000000..82ae2e8b8 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs @@ -0,0 +1,26 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class CropTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldCrop(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Crop(image.Width / 2, image.Height / 2) + .DebugSave(provider, null, Extensions.Bmp); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/CropTest.cs b/tests/ImageSharp.Tests/Processors/Filters/CropTest.cs deleted file mode 100644 index 6713d0d38..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/CropTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class CropTest : FileTestBase - { - [Fact] - public void ImageShouldApplyCropSampler() - { - string path = this.CreateOutputDirectory("Crop"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Crop(image.Width / 2, image.Height / 2).Save(output); - } - } - } - } -} \ No newline at end of file From 0a8eeedb5f5d6b69f2a02875f0d0780935dcb9cc Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 17:18:00 +1000 Subject: [PATCH 61/84] EntropyCrop --- .../Processing/Transforms/EntropyCropTest.cs | 33 +++++++++++++++ .../Processors/Filters/EntropyCropTest.cs | 40 ------------------- 2 files changed, 33 insertions(+), 40 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/EntropyCropTest.cs diff --git a/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs new file mode 100644 index 000000000..5b1dd0442 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class EntropyCropTest : FileTestBase + { + public static readonly TheoryData EntropyCropValues + = new TheoryData + { + .25F, + .75F + }; + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(EntropyCropValues), StandardPixelType)] + public void ImageShouldEntropyCrop(TestImageProvider provider, float value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.EntropyCrop(value) + .DebugSave(provider, value, Extensions.Bmp); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/EntropyCropTest.cs b/tests/ImageSharp.Tests/Processors/Filters/EntropyCropTest.cs deleted file mode 100644 index 710e23e37..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/EntropyCropTest.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class EntropyCropTest : FileTestBase - { - public static readonly TheoryData EntropyCropValues - = new TheoryData - { - .25f , - .75f , - }; - - [Theory] - [MemberData(nameof(EntropyCropValues))] - public void ImageShouldApplyEntropyCropSampler(float value) - { - string path = this.CreateOutputDirectory("EntropyCrop"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.EntropyCrop(value).Save(output); - } - } - } - } -} \ No newline at end of file From 0496b0d85c0e751589117a6a188f28142c9afad1 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 17:28:18 +1000 Subject: [PATCH 62/84] Flip --- .../Processing/Transforms/FlipTests.cs | 37 ++++++++++++++++ .../Processors/Filters/FlipTests.cs | 42 ------------------- 2 files changed, 37 insertions(+), 42 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs diff --git a/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs new file mode 100644 index 000000000..e002ebc70 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs @@ -0,0 +1,37 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms +{ + using ImageSharp.PixelFormats; + using ImageSharp.Processing; + + using Xunit; + + public class FlipTests : FileTestBase + { + public static readonly string[] FlipFiles = { TestImages.Bmp.F }; + + public static readonly TheoryData FlipValues + = new TheoryData + { + { FlipType.None }, + { FlipType.Vertical }, + { FlipType.Horizontal }, + }; + + [Theory] + [WithFileCollection(nameof(FlipFiles), nameof(FlipValues), StandardPixelType)] + public void ImageShouldFlip(TestImageProvider provider, FlipType flipType) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Flip(flipType) + .DebugSave(provider, flipType, Extensions.Bmp); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs b/tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs deleted file mode 100644 index c10eac430..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using ImageSharp.Processing; - using Xunit; - - public class FlipTests : FileTestBase - { - public static readonly TheoryData FlipValues - = new TheoryData - { - { FlipType.None }, - { FlipType.Vertical }, - { FlipType.Horizontal }, - }; - - [Theory] - [MemberData(nameof(FlipValues))] - public void ImageShouldFlip(FlipType flipType) - { - string path = this.CreateOutputDirectory("Flip"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(flipType); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Flip(flipType).Save(output); - } - } - } - } -} \ No newline at end of file From 2bd0c2c9bad55f2ff8c7433ca5ff1c1aa6f61683 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 22:45:58 +1000 Subject: [PATCH 63/84] Resize --- .../Transforms/Options/ResizeHelper.cs | 18 +- .../Processing/Transforms/Resize.cs | 22 +- .../Processing/Transforms/PadTest.cs | 35 ++ .../Transforms}/ResizeProfilingBenchmarks.cs | 17 +- .../Processing/Transforms/ResizeTests.cs | 273 ++++++++++++++ .../Processors/Filters/PadTest.cs | 31 -- .../Processors/Filters/ResizeTests.cs | 350 ------------------ .../TestUtilities/MeasureFixture.cs | 20 +- 8 files changed, 368 insertions(+), 398 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs rename tests/ImageSharp.Tests/{Processors/Filters => Processing/Transforms}/ResizeProfilingBenchmarks.cs (74%) create mode 100644 tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/PadTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs diff --git a/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs b/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs index c87688266..d9b9b5556 100644 --- a/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs @@ -399,6 +399,10 @@ namespace ImageSharp.Processing return new Rectangle(0, 0, source.Width, source.Height); } + // Fractional variants for preserving aspect ratio. + float percentHeight = MathF.Abs(height / (float)source.Height); + float percentWidth = MathF.Abs(width / (float)source.Width); + float sourceRatio = (float)source.Height / source.Width; // Find the shortest distance to go. @@ -419,8 +423,18 @@ namespace ImageSharp.Processing } else { - destinationWidth = width; - destinationHeight = height; + if (height > width) + { + destinationWidth = width; + destinationHeight = Convert.ToInt32(source.Height * percentWidth); + height = destinationHeight; + } + else + { + destinationHeight = height; + destinationWidth = Convert.ToInt32(source.Width * percentHeight); + width = destinationWidth; + } } // Replace the size to match the rectangle. diff --git a/src/ImageSharp/Processing/Transforms/Resize.cs b/src/ImageSharp/Processing/Transforms/Resize.cs index 0ed682648..271a111ca 100644 --- a/src/ImageSharp/Processing/Transforms/Resize.cs +++ b/src/ImageSharp/Processing/Transforms/Resize.cs @@ -5,8 +5,6 @@ namespace ImageSharp { - using System; - using ImageSharp.PixelFormats; using ImageSharp.Processing; @@ -58,6 +56,21 @@ namespace ImageSharp return Resize(source, size.Width, size.Height, new BicubicResampler(), false); } + /// + /// Resizes an image to the given . + /// + /// The pixel format. + /// The image to resize. + /// The target image size. + /// Whether to compress and expand the image color-space to gamma correct the image during processing. + /// The + /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image + public static Image Resize(this Image source, Size size, bool compand) + where TPixel : struct, IPixel + { + return Resize(source, size.Width, size.Height, new BicubicResampler(), compand); + } + /// /// Resizes an image to the given width and height. /// @@ -140,7 +153,7 @@ namespace ImageSharp /// Whether to compress and expand the image color-space to gamma correct the image during processing. /// The /// Passing zero for one of height or width will automatically preserve the aspect ratio of the original image - public static Image Resize(this Image source, int width, int height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, bool compand = false) + public static Image Resize(this Image source, int width, int height, IResampler sampler, Rectangle sourceRectangle, Rectangle targetRectangle, bool compand) where TPixel : struct, IPixel { if (width == 0 && height > 0) @@ -158,8 +171,7 @@ namespace ImageSharp Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); - ResizeProcessor processor = - new ResizeProcessor(sampler, width, height, targetRectangle) { Compand = compand }; + var processor = new ResizeProcessor(sampler, width, height, targetRectangle) { Compand = compand }; source.ApplyProcessor(processor, sourceRectangle); return source; diff --git a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs new file mode 100644 index 000000000..ee03193ae --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs @@ -0,0 +1,35 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class PadTest : FileTestBase + { + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ImageShouldPad(TestImageProvider provider) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Pad(image.Width + 50, image.Height + 50) + .DebugSave(provider, null, Extensions.Bmp); + + // Check pixels are empty + for (int y = 0; y < 25; y++) + { + for (int x = 0; x < 25; x++) + { + Assert.Equal(image[x, y], default(TPixel)); + } + } + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/ResizeProfilingBenchmarks.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs similarity index 74% rename from tests/ImageSharp.Tests/Processors/Filters/ResizeProfilingBenchmarks.cs rename to tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs index a743665d4..3f8a75b92 100644 --- a/tests/ImageSharp.Tests/Processors/Filters/ResizeProfilingBenchmarks.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs @@ -1,9 +1,13 @@ -namespace ImageSharp.Tests +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms { using System.IO; using System.Text; - using ImageSharp.PixelFormats; using ImageSharp.Processing; using ImageSharp.Processing.Processors; @@ -27,7 +31,7 @@ namespace ImageSharp.Tests this.Measure(this.ExecutionCount, () => { - using (Image image = new Image(width, height)) + using (var image = new Image(width, height)) { image.Resize(width / 4, height / 4); } @@ -37,11 +41,11 @@ namespace ImageSharp.Tests // [Fact] public void PrintWeightsData() { - ResizeProcessor proc = new ResizeProcessor(new BicubicResampler(), 200, 200); + var proc = new ResizeProcessor(new BicubicResampler(), 200, 200); ResamplingWeightedProcessor.WeightsBuffer weights = proc.PrecomputeWeights(200, 500); - StringBuilder bld = new StringBuilder(); + var bld = new StringBuilder(); foreach (ResamplingWeightedProcessor.WeightsWindow window in weights.Weights) { @@ -51,12 +55,13 @@ namespace ImageSharp.Tests bld.Append(value); bld.Append("| "); } + bld.AppendLine(); } File.WriteAllText("BicubicWeights.MD", bld.ToString()); - //this.Output.WriteLine(bld.ToString()); + // this.Output.WriteLine(bld.ToString()); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs new file mode 100644 index 000000000..8244f17c3 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs @@ -0,0 +1,273 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms +{ + using ImageSharp.PixelFormats; + using ImageSharp.Processing; + + using Xunit; + + public class ResizeTests : FileTestBase + { + public static readonly string[] ResizeFiles = { TestImages.Jpeg.Baseline.Calliphora }; + + public static readonly TheoryData ReSamplers = + new TheoryData + { + { "Bicubic", new BicubicResampler() }, + { "Triangle", new TriangleResampler() }, + { "NearestNeighbor", new NearestNeighborResampler() }, + { "Box", new BoxResampler() }, + { "Lanczos3", new Lanczos3Resampler() }, + { "Lanczos5", new Lanczos5Resampler() }, + { "MitchellNetravali", new MitchellNetravaliResampler() }, + { "Lanczos8", new Lanczos8Resampler() }, + { "Hermite", new HermiteResampler() }, + { "Spline", new SplineResampler() }, + { "Robidoux", new RobidouxResampler() }, + { "RobidouxSharp", new RobidouxSharpResampler() }, + { "Welch", new WelchResampler() } + }; + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResize(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Resize(image.Width / 2, image.Height / 2, sampler, true) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeFromSourceRectangle(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var sourceRectangle = new Rectangle(image.Width / 8, image.Height / 8, image.Width / 4, image.Height / 4); + var destRectangle = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); + + image.Resize(image.Width, image.Height, sampler, sourceRectangle, destRectangle, false) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeWidthAndKeepAspect(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Resize(image.Width / 3, 0, sampler, false) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeHeightAndKeepAspect(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Resize(0, image.Height / 3, sampler, false) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeWithCropWidthMode(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new ResizeOptions + { + Sampler = sampler, + Size = new Size(image.Width / 2, image.Height) + }; + + image.Resize(options) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeWithCropHeightMode(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new ResizeOptions + { + Sampler = sampler, + Size = new Size(image.Width, image.Height / 2) + }; + + image.Resize(options) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeWithPadMode(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new ResizeOptions + { + Sampler = sampler, + Size = new Size(image.Width + 200, image.Height), + Mode = ResizeMode.Pad + }; + + image.Resize(options) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeWithBoxPadMode(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new ResizeOptions + { + Sampler = sampler, + Size = new Size(image.Width + 200, image.Height + 200), + Mode = ResizeMode.BoxPad + }; + + image.Resize(options) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeWithMaxMode(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new ResizeOptions + { + Sampler = sampler, + Size = new Size(300, 300), + Mode = ResizeMode.Max + }; + + image.Resize(options) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeWithMinMode(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new ResizeOptions + { + Sampler = sampler, + Size = new Size((int)MathF.Round(image.Width * .75F), (int)MathF.Round(image.Height * .95F)), + Mode = ResizeMode.Min + }; + + image.Resize(options) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + public void ImageShouldResizeWithStretchMode(TestImageProvider provider, string name, IResampler sampler) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new ResizeOptions + { + Sampler = sampler, + Size = new Size(image.Width / 2, image.Height), + Mode = ResizeMode.Stretch + }; + + image.Resize(options) + .DebugSave(provider, name, Extensions.Bmp); + } + } + + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void BicubicWindowOscillatesCorrectly(float x, float expected) + { + var sampler = new BicubicResampler(); + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void TriangleWindowOscillatesCorrectly(float x, float expected) + { + var sampler = new TriangleResampler(); + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-2, 0)] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 0)] + [InlineData(2, 0)] + public static void Lanczos3WindowOscillatesCorrectly(float x, float expected) + { + var sampler = new Lanczos3Resampler(); + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + + [Theory] + [InlineData(-4, 0)] + [InlineData(-2, 0)] + [InlineData(0, 1)] + [InlineData(2, 0)] + [InlineData(4, 0)] + public static void Lanczos5WindowOscillatesCorrectly(float x, float expected) + { + var sampler = new Lanczos5Resampler(); + float result = sampler.GetValue(x); + + Assert.Equal(result, expected); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/PadTest.cs b/tests/ImageSharp.Tests/Processors/Filters/PadTest.cs deleted file mode 100644 index 6095410a9..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/PadTest.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class PadTest : FileTestBase - { - [Fact] - public void ImageShouldApplyPadSampler() - { - string path = this.CreateOutputDirectory("Pad"); - - foreach (TestFile file in Files) - { - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.Pad(image.Width + 50, image.Height + 50).Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs b/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs deleted file mode 100644 index 8268c6b64..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs +++ /dev/null @@ -1,350 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageSharp.Tests -{ - using System; - using System.IO; - - using ImageSharp.PixelFormats; - - using ImageSharp.Processing; - using Xunit; - - public class ResizeTests : FileTestBase - { - public static readonly TheoryData ReSamplers = - new TheoryData - { - { "Bicubic", new BicubicResampler() }, - { "Triangle", new TriangleResampler() }, - { "NearestNeighbor", new NearestNeighborResampler() }, - - // Perf: Enable for local testing only - // { "Box", new BoxResampler() }, - // { "Lanczos3", new Lanczos3Resampler() }, - // { "Lanczos5", new Lanczos5Resampler() }, - { "MitchellNetravali", new MitchellNetravaliResampler() }, - - // { "Lanczos8", new Lanczos8Resampler() }, - // { "Hermite", new HermiteResampler() }, - // { "Spline", new SplineResampler() }, - // { "Robidoux", new RobidouxResampler() }, - // { "RobidouxSharp", new RobidouxSharpResampler() }, - // { "RobidouxSoft", new RobidouxSoftResampler() }, - // { "Welch", new WelchResampler() } - }; - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResize(string name, IResampler sampler) - { - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Resize(image.Width / 2, image.Height / 2, sampler, true).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeFromSourceRectangle(string name, IResampler sampler) - { - name = $"{name}-SourceRect"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - Rectangle sourceRectangle = new Rectangle(image.Width / 8, image.Height / 8, image.Width / 4, image.Height / 4); - Rectangle destRectangle = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2); - image.Resize(image.Width, image.Height, sampler, sourceRectangle, destRectangle, false).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeWidthAndKeepAspect(string name, IResampler sampler) - { - name = $"{name}-FixedWidth"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Resize(image.Width / 3, 0, sampler, false).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeHeightAndKeepAspect(string name, IResampler sampler) - { - name = $"{name}-FixedHeight"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Resize(0, image.Height / 3, sampler, false).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeWithCropWidthMode(string name, IResampler sampler) - { - name = $"{name}-CropWidth"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions - { - Sampler = sampler, - Size = new Size(image.Width / 2, image.Height) - }; - - image.Resize(options).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeWithCropHeightMode(string name, IResampler sampler) - { - name = $"{name}-CropHeight"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions - { - Sampler = sampler, - Size = new Size(image.Width, image.Height / 2) - }; - - image.Resize(options).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeWithPadMode(string name, IResampler sampler) - { - name = $"{name}-Pad"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions - { - Size = new Size(image.Width + 200, image.Height), - Mode = ResizeMode.Pad - }; - - image.Resize(options).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeWithBoxPadMode(string name, IResampler sampler) - { - name = $"{name}-BoxPad"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions - { - Sampler = sampler, - Size = new Size(image.Width + 200, image.Height + 200), - Mode = ResizeMode.BoxPad - }; - - image.Resize(options).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeWithMaxMode(string name, IResampler sampler) - { - name = $"{name}Max"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions - { - Sampler = sampler, - Size = new Size(300, 300), - Mode = ResizeMode.Max - }; - - image.Resize(options).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeWithMinMode(string name, IResampler sampler) - { - name = $"{name}-Min"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions - { - Sampler = sampler, - Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * .95F)), - Mode = ResizeMode.Min - }; - - image.Resize(options).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(ReSamplers))] - public void ImageShouldResizeWithStretchMode(string name, IResampler sampler) - { - name = $"{name}Stretch"; - - string path = this.CreateOutputDirectory("Resize"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(name); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - ResizeOptions options = new ResizeOptions - { - Sampler = sampler, - Size = new Size(image.Width / 2, image.Height), - Mode = ResizeMode.Stretch - }; - - image.Resize(options).Save(output); - } - } - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void BicubicWindowOscillatesCorrectly(float x, float expected) - { - BicubicResampler sampler = new BicubicResampler(); - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void TriangleWindowOscillatesCorrectly(float x, float expected) - { - TriangleResampler sampler = new TriangleResampler(); - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-2, 0)] - [InlineData(-1, 0)] - [InlineData(0, 1)] - [InlineData(1, 0)] - [InlineData(2, 0)] - public static void Lanczos3WindowOscillatesCorrectly(float x, float expected) - { - Lanczos3Resampler sampler = new Lanczos3Resampler(); - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - - [Theory] - [InlineData(-4, 0)] - [InlineData(-2, 0)] - [InlineData(0, 1)] - [InlineData(2, 0)] - [InlineData(4, 0)] - public static void Lanczos5WindowOscillatesCorrectly(float x, float expected) - { - Lanczos5Resampler sampler = new Lanczos5Resampler(); - float result = sampler.GetValue(x); - - Assert.Equal(result, expected); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/MeasureFixture.cs b/tests/ImageSharp.Tests/TestUtilities/MeasureFixture.cs index 1dadc4884..1a6bf5d8b 100644 --- a/tests/ImageSharp.Tests/TestUtilities/MeasureFixture.cs +++ b/tests/ImageSharp.Tests/TestUtilities/MeasureFixture.cs @@ -1,4 +1,9 @@ -namespace ImageSharp.Tests +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests { using System; using System.Diagnostics; @@ -24,8 +29,12 @@ /// The name of the operation to print to the output public void Measure(int times, Action action, [CallerMemberName] string operationName = null) { - if (this.EnablePrinting) this.Output?.WriteLine($"{operationName} X {times} ..."); - Stopwatch sw = Stopwatch.StartNew(); + if (this.EnablePrinting) + { + this.Output?.WriteLine($"{operationName} X {times} ..."); + } + + var sw = Stopwatch.StartNew(); for (int i = 0; i < times; i++) { @@ -33,7 +42,10 @@ } sw.Stop(); - if (this.EnablePrinting) this.Output?.WriteLine($"{operationName} finished in {sw.ElapsedMilliseconds} ms"); + if (this.EnablePrinting) + { + this.Output?.WriteLine($"{operationName} finished in {sw.ElapsedMilliseconds} ms"); + } } /// From 6b07ff2b28bedab9a03a969ba3c7295e6d351fce Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 30 May 2017 23:52:06 +1000 Subject: [PATCH 64/84] Rotate, Skew --- tests/ImageSharp.Sandbox46/Program.cs | 1 + .../Processing/Transforms/AutoOrientTests.cs | 6 +- .../Processing/Transforms/RotateFlipTests.cs | 39 +++++++++++ .../Processing/Transforms/RotateTests.cs | 55 +++++++++++++++ .../Processing/Transforms/SkewTest.cs | 33 +++++++++ .../Processors/Filters/RotateFlipTest.cs | 44 ------------ .../Processors/Filters/RotateTest.cs | 67 ------------------- .../Processors/Filters/SkewTest.cs | 42 ------------ 8 files changed, 131 insertions(+), 156 deletions(-) create mode 100644 tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs create mode 100644 tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs create mode 100644 tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs delete mode 100644 tests/ImageSharp.Tests/Processors/Filters/SkewTest.cs diff --git a/tests/ImageSharp.Sandbox46/Program.cs b/tests/ImageSharp.Sandbox46/Program.cs index 7ea459aae..b882de0cc 100644 --- a/tests/ImageSharp.Sandbox46/Program.cs +++ b/tests/ImageSharp.Sandbox46/Program.cs @@ -10,6 +10,7 @@ namespace ImageSharp.Sandbox46 using ImageSharp.Tests; using ImageSharp.Tests.Colors; + using ImageSharp.Tests.Processing.Transforms; using Xunit.Abstractions; diff --git a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs index bae1b8332..d77a54c4f 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // @@ -39,9 +39,9 @@ namespace ImageSharp.Tests.Processing.Transforms image.MetaData.ExifProfile.SetValue(ExifTag.Orientation, orientation); image.RotateFlip(rotateType, flipType) - .DebugSave(provider, "before", Extensions.Bmp) + .DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "1_before"), Extensions.Bmp) .AutoOrient() - .DebugSave(provider, "after", Extensions.Bmp); + .DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "2_after"), Extensions.Bmp); } } } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs new file mode 100644 index 000000000..bdea4b223 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs @@ -0,0 +1,39 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms +{ + using ImageSharp.PixelFormats; + using ImageSharp.Processing; + + using Xunit; + + public class RotateFlipTests : FileTestBase + { + public static readonly string[] FlipFiles = { TestImages.Bmp.F }; + + public static readonly TheoryData RotateFlipValues + = new TheoryData + { + { RotateType.None, FlipType.Vertical }, + { RotateType.None, FlipType.Horizontal }, + { RotateType.Rotate90, FlipType.None }, + { RotateType.Rotate180, FlipType.None }, + { RotateType.Rotate270, FlipType.None }, + }; + + [Theory] + [WithFileCollection(nameof(FlipFiles), nameof(RotateFlipValues), StandardPixelType)] + public void ImageShouldRotateFlip(TestImageProvider provider, RotateType rotateType, FlipType flipType) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.RotateFlip(rotateType, flipType) + .DebugSave(provider, string.Join("_", rotateType, flipType), Extensions.Bmp); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs new file mode 100644 index 000000000..42e89bb5f --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs @@ -0,0 +1,55 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms +{ + using ImageSharp.PixelFormats; + using ImageSharp.Processing; + + using Xunit; + + public class RotateTests : FileTestBase + { + public static readonly TheoryData RotateFloatValues + = new TheoryData + { + 170, + -170 + }; + + public static readonly TheoryData RotateEnumValues + = new TheoryData + { + RotateType.None, + RotateType.Rotate90, + RotateType.Rotate180, + RotateType.Rotate270 + }; + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(RotateFloatValues), StandardPixelType)] + public void ImageShouldRotate(TestImageProvider provider, float value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Rotate(value) + .DebugSave(provider, value, Extensions.Bmp); + } + } + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(RotateEnumValues), StandardPixelType)] + public void ImageShouldRotateEnum(TestImageProvider provider, RotateType value) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Rotate(value) + .DebugSave(provider, value, Extensions.Bmp); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs new file mode 100644 index 000000000..2c393acac --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Processing.Transforms +{ + using ImageSharp.PixelFormats; + + using Xunit; + + public class SkewTest : FileTestBase + { + public static readonly TheoryData SkewValues + = new TheoryData + { + { 20, 10 }, + { -20, -10 } + }; + + [Theory] + [WithFileCollection(nameof(DefaultFiles), nameof(SkewValues), StandardPixelType)] + public void ImageShouldSkew(TestImageProvider provider, float x, float y) + where TPixel : struct, IPixel + { + using (Image image = provider.GetImage()) + { + image.Skew(x, y) + .DebugSave(provider, string.Join("_", x, y), Extensions.Bmp); + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs b/tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs deleted file mode 100644 index 5f75e98e3..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using ImageSharp.Processing; - using Xunit; - - public class RotateFlipTest : FileTestBase - { - public static readonly TheoryData RotateFlipValues - = new TheoryData - { - { RotateType.None, FlipType.Vertical }, - { RotateType.None, FlipType.Horizontal }, - { RotateType.Rotate90, FlipType.None }, - { RotateType.Rotate180, FlipType.None }, - { RotateType.Rotate270, FlipType.None }, - }; - - [Theory] - [MemberData(nameof(RotateFlipValues))] - public void ImageShouldRotateFlip(RotateType rotateType, FlipType flipType) - { - string path = this.CreateOutputDirectory("RotateFlip"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(rotateType + "-" + flipType); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.RotateFlip(rotateType, flipType).Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs b/tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs deleted file mode 100644 index 8ced88ce6..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using ImageSharp.Processing; - using Xunit; - - public class RotateTest : FileTestBase - { - public static readonly TheoryData RotateFloatValues - = new TheoryData - { - 170 , - -170 , - }; - - public static readonly TheoryData RotateEnumValues - = new TheoryData - { - RotateType.None, - RotateType.Rotate90, - RotateType.Rotate180, - RotateType.Rotate270 - }; - - [Theory] - [MemberData(nameof(RotateFloatValues))] - public void ImageShouldApplyRotateSampler(float value) - { - string path = this.CreateOutputDirectory("Rotate"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Rotate(value).Save(output); - } - } - } - - [Theory] - [MemberData(nameof(RotateEnumValues))] - public void ImageShouldApplyRotateSampler(RotateType value) - { - string path = this.CreateOutputDirectory("Rotate"); - - foreach (TestFile file in Files) - { - string filename = file.GetFileName(value); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Rotate(value).Save(output); - } - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processors/Filters/SkewTest.cs b/tests/ImageSharp.Tests/Processors/Filters/SkewTest.cs deleted file mode 100644 index d096b3913..000000000 --- a/tests/ImageSharp.Tests/Processors/Filters/SkewTest.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Tests -{ - using System.IO; - - using ImageSharp.PixelFormats; - - using Xunit; - - public class SkewTest : FileTestBase - { - public static readonly TheoryData SkewValues - = new TheoryData - { - { 20, 10 }, - { -20, -10 } - }; - - [Theory] - [MemberData(nameof(SkewValues))] - public void ImageShouldApplySkewSampler(float x, float y) - { - string path = this.CreateOutputDirectory("Skew"); - - // Matches live example - // http://www.w3schools.com/css/tryit.asp?filename=trycss3_transform_skew - foreach (TestFile file in Files) - { - string filename = file.GetFileName(x + "-" + y); - using (Image image = file.CreateImage()) - using (FileStream output = File.OpenWrite($"{path}/{filename}")) - { - image.Skew(x, y).Save(output); - } - } - } - } -} \ No newline at end of file From 45d2fe6ed79a1c389706e90d72441276d75d3986 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 31 May 2017 00:01:24 +1000 Subject: [PATCH 65/84] Begin general tests --- .../Formats/GeneralFormatTests.cs | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index b47df8395..411cc600a 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -13,22 +13,16 @@ namespace ImageSharp.Tests public class GeneralFormatTests : FileTestBase { - [Fact] - public void ResolutionShouldChange() + [Theory] + [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + public void ResolutionShouldChange(TestImageProvider provider) + where TPixel : struct, IPixel { - string path = this.CreateOutputDirectory("Resolution"); - - foreach (TestFile file in Files) + using (Image image = provider.GetImage()) { - using (Image image = file.CreateImage()) - { - using (FileStream output = File.OpenWrite($"{path}/{file.FileName}")) - { - image.MetaData.VerticalResolution = 150; - image.MetaData.HorizontalResolution = 150; - image.Save(output); - } - } + image.MetaData.VerticalResolution = 150; + image.MetaData.HorizontalResolution = 150; + image.DebugSave(provider, null, Extensions.Bmp); } } From 4ab9228508cba6685e220346810d37aaa9727d66 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 30 May 2017 08:08:59 +0100 Subject: [PATCH 66/84] replace outlineing logic with path generation. --- src/ImageSharp.Drawing/DrawPath.cs | 110 ---------- src/ImageSharp.Drawing/Drawable.cs | 51 ----- src/ImageSharp.Drawing/Paths/DrawPath.cs | 2 +- src/ImageSharp.Drawing/Paths/ShapePath.cs | 90 +------- src/ImageSharp.Drawing/Paths/ShapeRegion.cs | 8 +- src/ImageSharp.Drawing/Pens/IPen.cs | 31 +-- src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs | 192 +----------------- .../Processors/DrawPathProcessor.cs | 140 ------------- .../Processors/FillRegionProcessor.cs | 15 +- src/ImageSharp.Drawing/Region.cs | 8 +- .../Drawing/FillRegionProcessorTests.cs | 54 ++++- .../Drawing/Paths/DrawBeziersTests.cs | 163 --------------- .../Drawing/Paths/DrawLinesTests.cs | 160 --------------- .../Drawing/Paths/DrawPath.cs | 149 -------------- .../Drawing/Paths/DrawPolygon.cs | 161 --------------- .../Drawing/Paths/DrawRectangle.cs | 177 ---------------- .../Drawing/Paths/ShapePathTests.cs | 105 +--------- .../Drawing/Paths/ShapeRegionTests.cs | 4 +- .../ImageSharp.Tests/Drawing/Text/DrawText.cs | 12 +- 19 files changed, 116 insertions(+), 1516 deletions(-) delete mode 100644 src/ImageSharp.Drawing/DrawPath.cs delete mode 100644 src/ImageSharp.Drawing/Drawable.cs delete mode 100644 src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawBeziersTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawLinesTests.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawPath.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawPolygon.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawRectangle.cs diff --git a/src/ImageSharp.Drawing/DrawPath.cs b/src/ImageSharp.Drawing/DrawPath.cs deleted file mode 100644 index 09d3dbb02..000000000 --- a/src/ImageSharp.Drawing/DrawPath.cs +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp -{ - using Drawing; - using Drawing.Brushes; - using Drawing.Pens; - using Drawing.Processors; - using ImageSharp.PixelFormats; - - /// - /// Extension methods for the type. - /// - public static partial class ImageExtensions - { - /// - /// Draws the outline of the region with the provided pen. - /// - /// The type of the color. - /// The image this method extends. - /// The pen. - /// The path. - /// The options. - /// The . - public static Image Draw(this Image source, IPen pen, Drawable path, GraphicsOptions options) - where TPixel : struct, IPixel - { - return source.Apply(new DrawPathProcessor(pen, path, options)); - } - - /// - /// Draws the outline of the polygon with the provided pen. - /// - /// The type of the color. - /// The image this method extends. - /// The pen. - /// The path. - /// The . - public static Image Draw(this Image source, IPen pen, Drawable path) - where TPixel : struct, IPixel - { - return source.Draw(pen, path, GraphicsOptions.Default); - } - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The type of the color. - /// The image this method extends. - /// The brush. - /// The thickness. - /// The path. - /// The options. - /// The . - public static Image Draw(this Image source, IBrush brush, float thickness, Drawable path, GraphicsOptions options) - where TPixel : struct, IPixel - { - return source.Draw(new Pen(brush, thickness), path, options); - } - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The type of the color. - /// The image this method extends. - /// The brush. - /// The thickness. - /// The path. - /// The . - public static Image Draw(this Image source, IBrush brush, float thickness, Drawable path) - where TPixel : struct, IPixel - { - return source.Draw(new Pen(brush, thickness), path); - } - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The type of the color. - /// The image this method extends. - /// The color. - /// The thickness. - /// The path. - /// The options. - /// The . - public static Image Draw(this Image source, TPixel color, float thickness, Drawable path, GraphicsOptions options) - where TPixel : struct, IPixel - { - return source.Draw(new SolidBrush(color), thickness, path, options); - } - - /// - /// Draws the outline of the polygon with the provided brush at the provided thickness. - /// - /// The type of the color. - /// The image this method extends. - /// The color. - /// The thickness. - /// The path. - /// The . - public static Image Draw(this Image source, TPixel color, float thickness, Drawable path) - where TPixel : struct, IPixel - { - return source.Draw(new SolidBrush(color), thickness, path); - } - } -} diff --git a/src/ImageSharp.Drawing/Drawable.cs b/src/ImageSharp.Drawing/Drawable.cs deleted file mode 100644 index 62f5e62c1..000000000 --- a/src/ImageSharp.Drawing/Drawable.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Drawing -{ - /// - /// Represents a path or set of paths that can be drawn as an outline. - /// - public abstract class Drawable - { - /// - /// Gets the maximum number of intersections to could be returned. - /// - public abstract int MaxIntersections { get; } - - /// - /// Gets the bounds. - /// - public abstract Rectangle Bounds { get; } - - /// - /// Gets the point information for the specified x and y location. - /// - /// The x. - /// The y. - /// Information about the point in relation to a drawable edge - public abstract PointInfo GetPointInfo(int x, int y); - - /// - /// Scans the X axis for intersections. - /// - /// The x. - /// The buffer. - /// The length. - /// The offset. - /// The number of intersections found. - public abstract int ScanX(int x, float[] buffer, int length, int offset); - - /// - /// Scans the Y axis for intersections. - /// - /// The position along the y axis to find intersections. - /// The buffer. - /// The length. - /// The offset. - /// The number of intersections found. - public abstract int ScanY(int y, float[] buffer, int length, int offset); - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Paths/DrawPath.cs b/src/ImageSharp.Drawing/Paths/DrawPath.cs index 176539663..eb12a2606 100644 --- a/src/ImageSharp.Drawing/Paths/DrawPath.cs +++ b/src/ImageSharp.Drawing/Paths/DrawPath.cs @@ -28,7 +28,7 @@ namespace ImageSharp public static Image Draw(this Image source, IPen pen, IPath path, GraphicsOptions options) where TPixel : struct, IPixel { - return source.Draw(pen, new ShapePath(path), options); + return source.Fill(pen.StokeFill, new ShapePath(path, pen), options); } /// diff --git a/src/ImageSharp.Drawing/Paths/ShapePath.cs b/src/ImageSharp.Drawing/Paths/ShapePath.cs index d0376ccc1..63c814f2d 100644 --- a/src/ImageSharp.Drawing/Paths/ShapePath.cs +++ b/src/ImageSharp.Drawing/Paths/ShapePath.cs @@ -1,12 +1,12 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageSharp.Drawing { + using System; using System.Buffers; - using System.Collections.Immutable; using System.Numerics; using SixLabors.Shapes; @@ -14,91 +14,19 @@ namespace ImageSharp.Drawing using Rectangle = ImageSharp.Rectangle; /// - /// A drawable mapping between a and a drawable region. + /// A mapping between a and a region. /// - internal class ShapePath : Drawable + internal class ShapePath : ShapeRegion { /// /// Initializes a new instance of the class. /// - /// The path. - public ShapePath(IPath path) + /// The shape. + /// The pen to apply to the shape. + // SixLabors.shape willbe moving to a Span/ReadOnlySpan based API shortly use ToArray for now. + public ShapePath(IPath shape, Pens.IPen pen) + : base(shape.GenerateOutline(pen.StrokeWidth, pen.StrokePattern.ToArray())) { - this.Path = path; - this.Bounds = path.Bounds.Convert(); - } - - /// - /// Gets the fillable shape - /// - public IPath Path { get; } - - /// - public override int MaxIntersections => this.Path.MaxIntersections; - - /// - public override Rectangle Bounds { get; } - - /// - public override int ScanX(int x, float[] buffer, int length, int offset) - { - Vector2 start = new Vector2(x, this.Bounds.Top - 1); - Vector2 end = new Vector2(x, this.Bounds.Bottom + 1); - Vector2[] innerbuffer = ArrayPool.Shared.Rent(length); - try - { - int count = this.Path.FindIntersections(start, end, innerbuffer, length, 0); - - for (int i = 0; i < count; i++) - { - buffer[i + offset] = innerbuffer[i].Y; - } - - return count; - } - finally - { - ArrayPool.Shared.Return(innerbuffer); - } - } - - /// - public override int ScanY(int y, float[] buffer, int length, int offset) - { - Vector2 start = new Vector2(this.Bounds.Left - 1, y); - Vector2 end = new Vector2(this.Bounds.Right + 1, y); - Vector2[] innerbuffer = ArrayPool.Shared.Rent(length); - try - { - int count = this.Path.FindIntersections(start, end, innerbuffer, length, 0); - - for (int i = 0; i < count; i++) - { - buffer[i + offset] = innerbuffer[i].X; - } - - return count; - } - finally - { - ArrayPool.Shared.Return(innerbuffer); - } - } - - /// - public override PointInfo GetPointInfo(int x, int y) - { - Vector2 point = new Vector2(x, y); - SixLabors.Shapes.PointInfo dist = this.Path.Distance(point); - - return new PointInfo - { - DistanceAlongPath = dist.DistanceAlongPath, - DistanceFromPath = - dist.DistanceFromPath < 0 - ? -dist.DistanceFromPath - : dist.DistanceFromPath - }; } } } diff --git a/src/ImageSharp.Drawing/Paths/ShapeRegion.cs b/src/ImageSharp.Drawing/Paths/ShapeRegion.cs index 086894531..9dbf52285 100644 --- a/src/ImageSharp.Drawing/Paths/ShapeRegion.cs +++ b/src/ImageSharp.Drawing/Paths/ShapeRegion.cs @@ -40,18 +40,18 @@ namespace ImageSharp.Drawing public override Rectangle Bounds { get; } /// - public override int Scan(float y, float[] buffer, int length, int offset) + public override int Scan(float y, Span buffer) { Vector2 start = new Vector2(this.Bounds.Left - 1, y); Vector2 end = new Vector2(this.Bounds.Right + 1, y); - Vector2[] innerbuffer = ArrayPool.Shared.Rent(length); + Vector2[] innerbuffer = ArrayPool.Shared.Rent(buffer.Length); try { - int count = this.Shape.FindIntersections(start, end, innerbuffer, length, 0); + int count = this.Shape.FindIntersections(start, end, innerbuffer, buffer.Length, 0); for (int i = 0; i < count; i++) { - buffer[i + offset] = innerbuffer[i].X; + buffer[i] = innerbuffer[i].X; } return count; diff --git a/src/ImageSharp.Drawing/Pens/IPen.cs b/src/ImageSharp.Drawing/Pens/IPen.cs index 81d273091..affcb9d1f 100644 --- a/src/ImageSharp.Drawing/Pens/IPen.cs +++ b/src/ImageSharp.Drawing/Pens/IPen.cs @@ -12,21 +12,28 @@ namespace ImageSharp.Drawing.Pens /// Interface representing a Pen /// /// The type of the color. - public interface IPen + public interface IPen : IPen where TPixel : struct, IPixel { /// - /// Creates the applicator for applying this pen to an Image + /// Gets the stoke fill. /// - /// The source image. - /// The region the pen will be applied to. - /// The currently active graphic options. - /// - /// Returns a the applicator for the pen. - /// - /// - /// 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(ImageBase source, RectangleF region, GraphicsOptions options); + IBrush StokeFill { get; } + } + + /// + /// Iterface represting the pattern and size of the stroke to apply with a Pen. + /// + public interface IPen + { + /// + /// Gets the width to apply to the stroke + /// + float StrokeWidth { get; } + + /// + /// Gets the stoke pattern. + /// + System.ReadOnlySpan StrokePattern { get; } } } diff --git a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs index a5639e49a..0a0c81f9c 100644 --- a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs +++ b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs @@ -5,6 +5,7 @@ namespace ImageSharp.Drawing.Pens { + using System; using System.Numerics; using ImageSharp.Drawing.Brushes; @@ -48,8 +49,8 @@ namespace ImageSharp.Drawing.Pens /// The pattern. public Pen(IBrush brush, float width, float[] pattern) { - this.Brush = brush; - this.Width = width; + this.StokeFill = brush; + this.StrokeWidth = width; this.pattern = pattern; } @@ -78,190 +79,17 @@ namespace ImageSharp.Drawing.Pens /// /// The pen. internal Pen(Pen pen) - : this(pen.Brush, pen.Width, pen.pattern) + : this(pen.StokeFill, pen.StrokeWidth, pen.pattern) { } - /// - /// Gets the brush. - /// - /// - /// The brush. - /// - public IBrush Brush { get; } - - /// - /// Gets the width. - /// - /// - /// The width. - /// - public float Width { get; } - - /// - /// Creates the applicator for applying this pen to an Image - /// - /// The source image. - /// The region the pen will be applied to. - /// The Graphics options - /// - /// Returns a the applicator for the pen. - /// - /// - /// 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(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(source, this.Brush, region, this.Width, options); - } - - return new PatternPenApplicator(source, this.Brush, region, this.Width, this.pattern, options); - } - - private class SolidPenApplicator : PenApplicator - { - private readonly BrushApplicator brush; - private readonly float halfWidth; - - public SolidPenApplicator(ImageBase sourcePixels, IBrush brush, RectangleF region, float width, GraphicsOptions options) - { - this.brush = brush.CreateApplicator(sourcePixels, region, options); - this.halfWidth = width / 2; - this.RequiredRegion = RectangleF.Inflate(region, width, width); - } - - public override RectangleF RequiredRegion - { - get; - } - - public override void Dispose() - { - this.brush.Dispose(); - } - - public override ColoredPointInfo GetColor(int x, int y, PointInfo info) - { - var result = default(ColoredPointInfo); - result.Color = this.brush[x, y]; - - if (info.DistanceFromPath < this.halfWidth) - { - // inside strip - result.DistanceFromElement = 0; - } - else - { - result.DistanceFromElement = info.DistanceFromPath - this.halfWidth; - } - - return result; - } - } - - private class PatternPenApplicator : PenApplicator - { - private readonly BrushApplicator brush; - private readonly float halfWidth; - private readonly float[] pattern; - private readonly float totalLength; - - public PatternPenApplicator(ImageBase source, IBrush brush, RectangleF region, float width, float[] pattern, GraphicsOptions options) - { - this.brush = brush.CreateApplicator(source, region, options); - this.halfWidth = width / 2; - this.totalLength = 0; - - this.pattern = new float[pattern.Length + 1]; - this.pattern[0] = 0; - for (int i = 0; i < pattern.Length; i++) - { - this.totalLength += pattern[i] * width; - this.pattern[i + 1] = this.totalLength; - } - - this.RequiredRegion = RectangleF.Inflate(region, width, width); - } - - public override RectangleF RequiredRegion - { - get; - } - - public override void Dispose() - { - this.brush.Dispose(); - } - - public override ColoredPointInfo GetColor(int x, int y, PointInfo info) - { - var infoResult = default(ColoredPointInfo); - infoResult.DistanceFromElement = float.MaxValue; // is really outside the element - - float length = info.DistanceAlongPath % this.totalLength; + /// + public IBrush StokeFill { get; } - // we can treat the DistanceAlongPath and DistanceFromPath as x,y coords for the pattern - // we need to calcualte the distance from the outside edge of the pattern - // and set them on the ColoredPointInfo along with the color. - infoResult.Color = this.brush[x, y]; + /// + public float StrokeWidth { get; } - float distanceWAway = 0; - - if (info.DistanceFromPath < this.halfWidth) - { - // inside strip - distanceWAway = 0; - } - else - { - distanceWAway = info.DistanceFromPath - this.halfWidth; - } - - for (int i = 0; i < this.pattern.Length - 1; i++) - { - float start = this.pattern[i]; - float end = this.pattern[i + 1]; - - if (length >= start && length < end) - { - // in section - if (i % 2 == 0) - { - // solid part return the maxDistance - infoResult.DistanceFromElement = distanceWAway; - return infoResult; - } - else - { - // this is a none solid part - float distanceFromStart = length - start; - float distanceFromEnd = end - length; - - float closestEdge = MathF.Min(distanceFromStart, distanceFromEnd); - - float distanceAcross = closestEdge; - - if (distanceWAway > 0) - { - infoResult.DistanceFromElement = new Vector2(distanceAcross, distanceWAway).Length(); - } - else - { - infoResult.DistanceFromElement = closestEdge; - } - - return infoResult; - } - } - } - - return infoResult; - } - } + /// + public ReadOnlySpan StrokePattern => this.pattern; } } diff --git a/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs b/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs deleted file mode 100644 index d40c71f7e..000000000 --- a/src/ImageSharp.Drawing/Processors/DrawPathProcessor.cs +++ /dev/null @@ -1,140 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Drawing.Processors -{ - using System; - using System.Threading.Tasks; - - using ImageSharp.Memory; - using ImageSharp.PixelFormats; - using ImageSharp.Processing; - using Pens; - - /// - /// Draws a path using the processor pipeline - /// - /// The type of the color. - /// - internal class DrawPathProcessor : ImageProcessor - where TPixel : struct, IPixel - { - private const float AntialiasFactor = 1f; - private const int PaddingFactor = 1; // needs to been the same or greater than AntialiasFactor - - /// - /// Initializes a new instance of the class. - /// - /// The details how to draw the outline/path. - /// The details of the paths and outlines to draw. - /// The drawing configuration options. - public DrawPathProcessor(IPen pen, Drawable drawable, GraphicsOptions options) - { - this.Path = drawable; - this.Pen = pen; - this.Options = options; - } - - /// - /// Gets the graphics options. - /// - public GraphicsOptions Options { get; } - - /// - /// Gets the pen. - /// - public IPen Pen { get; } - - /// - /// Gets the path. - /// - public Drawable Path { get; } - - /// - protected override void OnApply(ImageBase source, Rectangle sourceRectangle) - { - using (PenApplicator applicator = this.Pen.CreateApplicator(source, this.Path.Bounds, this.Options)) - { - var rect = Rectangle.Ceiling(applicator.RequiredRegion); - - int polyStartY = rect.Y - PaddingFactor; - int polyEndY = rect.Bottom + PaddingFactor; - int startX = rect.X - PaddingFactor; - int endX = rect.Right + PaddingFactor; - - int minX = Math.Max(sourceRectangle.Left, startX); - int maxX = Math.Min(sourceRectangle.Right, endX); - int minY = Math.Max(sourceRectangle.Top, polyStartY); - int maxY = Math.Min(sourceRectangle.Bottom, polyEndY); - - // Align start/end positions. - minX = Math.Max(0, minX); - maxX = Math.Min(source.Width, maxX); - minY = Math.Max(0, minY); - maxY = Math.Min(source.Height, maxY); - - // Reset offset if necessary. - if (minX > 0) - { - startX = 0; - } - - if (minY > 0) - { - polyStartY = 0; - } - - int width = maxX - minX; - PixelBlender blender = PixelOperations.Instance.GetPixelBlender(this.Options.BlenderMode); - - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - int offsetY = y - polyStartY; - - using (var amount = new Buffer(width)) - using (var colors = new Buffer(width)) - { - for (int i = 0; i < width; i++) - { - int x = i + minX; - int offsetX = x - startX; - PointInfo info = this.Path.GetPointInfo(offsetX, offsetY); - ColoredPointInfo color = applicator.GetColor(offsetX, offsetY, info); - amount[i] = (this.Opacity(color.DistanceFromElement) * this.Options.BlendPercentage).Clamp(0, 1); - colors[i] = color.Color; - } - - Span destination = source.GetRowSpan(offsetY).Slice(minX - startX, width); - blender.Blend(destination, destination, colors, amount); - } - }); - } - } - - /// - /// Returns the correct opacity for the given distance. - /// - /// Thw distance from the central point. - /// The - private float Opacity(float distance) - { - if (distance <= 0) - { - return 1; - } - - if (this.Options.Antialias && distance < AntialiasFactor) - { - return 1 - (distance / AntialiasFactor); - } - - return 0; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs index ae828e112..8224b234d 100644 --- a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs @@ -93,6 +93,7 @@ namespace ImageSharp.Drawing.Processors using (BrushApplicator applicator = this.Brush.CreateApplicator(source, rect, this.Options)) { float[] buffer = arrayPool.Rent(maxIntersections); + Span bufferSpan = buffer.AsSpan().Slice(0, maxIntersections); int scanlineWidth = maxX - minX; using (var scanline = new Buffer(scanlineWidth)) { @@ -116,14 +117,14 @@ namespace ImageSharp.Drawing.Processors float subpixelFractionPoint = subpixelFraction / subpixelCount; for (float subPixel = (float)y; subPixel < y + 1; subPixel += subpixelFraction) { - int pointsFound = region.Scan(subPixel, buffer, maxIntersections, 0); + int pointsFound = region.Scan(subPixel, bufferSpan); if (pointsFound == 0) { // nothing on this line skip continue; } - QuickSort(buffer, pointsFound); + QuickSort(bufferSpan.Slice(0, pointsFound)); for (int point = 0; point < pointsFound; point += 2) { @@ -194,20 +195,20 @@ namespace ImageSharp.Drawing.Processors } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void Swap(float[] data, int left, int right) + private static void Swap(Span data, int left, int right) { float tmp = data[left]; data[left] = data[right]; data[right] = tmp; } - private static void QuickSort(float[] data, int size) + private static void QuickSort(Span data) { - int hi = Math.Min(data.Length - 1, size - 1); + int hi = Math.Min(data.Length - 1, data.Length - 1); QuickSort(data, 0, hi); } - private static void QuickSort(float[] data, int lo, int hi) + private static void QuickSort(Span data, int lo, int hi) { if (lo < hi) { @@ -217,7 +218,7 @@ namespace ImageSharp.Drawing.Processors } } - private static int Partition(float[] data, int lo, int hi) + private static int Partition(Span data, int lo, int hi) { float pivot = data[lo]; int i = lo - 1; diff --git a/src/ImageSharp.Drawing/Region.cs b/src/ImageSharp.Drawing/Region.cs index 8cab88502..687ee23fd 100644 --- a/src/ImageSharp.Drawing/Region.cs +++ b/src/ImageSharp.Drawing/Region.cs @@ -5,6 +5,8 @@ namespace ImageSharp.Drawing { + using System; + /// /// Represents a region of an image. /// @@ -19,7 +21,7 @@ namespace ImageSharp.Drawing /// Gets the bounding box that entirely surrounds this region. /// /// - /// This should always contains all possible points returned from . + /// This should always contains all possible points returned from . /// public abstract Rectangle Bounds { get; } @@ -28,9 +30,7 @@ namespace ImageSharp.Drawing /// /// The position along the y axis to find intersections. /// The buffer. - /// The length. - /// The offset. /// The number of intersections found. - public abstract int Scan(float y, float[] buffer, int length, int offset); + public abstract int Scan(float y, Span buffer); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs index c7b789da0..58e55c124 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs @@ -8,6 +8,9 @@ namespace ImageSharp.Tests.Drawing using Moq; using ImageSharp.PixelFormats; + using System; + using ImageSharp.Drawing.Pens; + using System.Numerics; public class FillRegionProcessorTests { @@ -26,14 +29,61 @@ namespace ImageSharp.Tests.Drawing Mock region = new Mock(); region.Setup(x => x.Bounds).Returns(bounds); - GraphicsOptions options = new GraphicsOptions(antialias) { + GraphicsOptions options = new GraphicsOptions(antialias) + { AntialiasSubpixelDepth = 1 }; FillRegionProcessor processor = new FillRegionProcessor(brush.Object, region.Object, options); Image img = new Image(1, 1); processor.Apply(img, bounds); - region.Verify(x => x.Scan(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(4)); + region.Verify(x => x.Scan(It.IsAny(), It.IsAny>()), Times.Exactly(4)); + } + + [Fact] + public void FillOffCanvas() + { + + ImageSharp.Rectangle bounds = new ImageSharp.Rectangle(-100, -10, 10, 10); + + Mock> brush = new Mock>(); + Mock region = new Mock(); + region.Setup(x => x.Bounds).Returns(bounds); + + region.Setup(x => x.MaxIntersections).Returns(10); + region.Setup(x => x.Scan(It.IsAny(), It.IsAny>())) + .Returns>((y, span) => + { + if (y < 5) + { + span[0] = -10f; + span[1] = 100f; + return 2; + } + return 0; + }); + + GraphicsOptions options = new GraphicsOptions(true) + { + }; + FillRegionProcessor processor = new FillRegionProcessor(brush.Object, region.Object, options); + Image img = new Image(10, 10); + processor.Apply(img, bounds); + } + + + + [Fact] + public void DrawOffCanvas() + { + + using (var img = new Image(10, 10)) + { + img.DrawLines(new Pen(Rgba32.Black, 10), new Vector2[] { + new Vector2(-10, 5), + new Vector2(20, 5), + }); + } } } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawBeziersTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawBeziersTests.cs deleted file mode 100644 index a9b2284e8..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawBeziersTests.cs +++ /dev/null @@ -1,163 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Paths -{ - using System; - - using ImageSharp.Drawing.Brushes; - - using Xunit; - using ImageSharp.Drawing; - using System.Numerics; - using SixLabors.Shapes; - using ImageSharp.Drawing.Processors; - using ImageSharp.Drawing.Pens; - using ImageSharp.PixelFormats; - - public class DrawBeziersTests : IDisposable - { - float thickness = 7.2f; - GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - Pen pen = new Pen(Rgba32.Firebrick, 99.9f); - Vector2[] points = new Vector2[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - }; - private ProcessorWatchingImage img; - - public DrawBeziersTests() - { - this.img = new Paths.ProcessorWatchingImage(10, 10); - } - - public void Dispose() - { - img.Dispose(); - } - - [Fact] - public void CorrectlySetsBrushThicknessAndPoints() - { - img.DrawBeziers(brush, thickness, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - Assert.NotNull(path.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - - BezierLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsBrushThicknessPointsAndOptions() - { - img.DrawBeziers(brush, thickness, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - BezierLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsColorThicknessAndPoints() - { - img.DrawBeziers(color, thickness, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - BezierLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsColorThicknessPointsAndOptions() - { - img.DrawBeziers(color, thickness, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - BezierLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsPenAndPoints() - { - img.DrawBeziers(pen, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - BezierLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Assert.Equal(pen, processor.Pen); - } - - [Fact] - public void CorrectlySetsPenPointsAndOptions() - { - img.DrawBeziers(pen, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - BezierLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Assert.Equal(pen, processor.Pen); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawLinesTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawLinesTests.cs deleted file mode 100644 index 3b7ba303d..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawLinesTests.cs +++ /dev/null @@ -1,160 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Paths -{ - using System; - - using ImageSharp.Drawing.Brushes; - using Xunit; - using ImageSharp.Drawing; - using System.Numerics; - using SixLabors.Shapes; - using ImageSharp.Drawing.Processors; - using ImageSharp.Drawing.Pens; - using ImageSharp.PixelFormats; - - public class DrawLinesTests : IDisposable - { - float thickness = 7.2f; - GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - Pen pen = new Pen(Rgba32.Gray, 99.9f); - Vector2[] points = new Vector2[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - }; - private ProcessorWatchingImage img; - - public DrawLinesTests() - { - this.img = new Paths.ProcessorWatchingImage(10, 10); - } - - public void Dispose() - { - img.Dispose(); - } - - [Fact] - public void CorrectlySetsBrushThicknessAndPoints() - { - img.DrawLines(brush, thickness, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsBrushThicknessPointsAndOptions() - { - img.DrawLines(brush, thickness, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsColorThicknessAndPoints() - { - img.DrawLines(color, thickness, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsColorThicknessPointsAndOptions() - { - img.DrawLines(color, thickness, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsPenAndPoints() - { - img.DrawLines(pen, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Assert.Equal(pen, processor.Pen); - } - - [Fact] - public void CorrectlySetsPenPointsAndOptions() - { - img.DrawLines(pen, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - SixLabors.Shapes.Path vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Assert.Equal(pen, processor.Pen); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPath.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPath.cs deleted file mode 100644 index 0bdcbdc08..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawPath.cs +++ /dev/null @@ -1,149 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Paths -{ - using System; - - using ImageSharp.Drawing.Brushes; - - using Xunit; - using ImageSharp.Drawing; - using System.Numerics; - using SixLabors.Shapes; - using ImageSharp.Drawing.Processors; - using ImageSharp.Drawing.Pens; - using ImageSharp.PixelFormats; - - public class DrawPath : IDisposable - { - float thickness = 7.2f; - GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - Pen pen = new Pen(Rgba32.Gray, 99.9f); - IPath path = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - private ProcessorWatchingImage img; - - public DrawPath() - { - this.img = new Paths.ProcessorWatchingImage(10, 10); - } - - public void Dispose() - { - img.Dispose(); - } - - [Fact] - public void CorrectlySetsBrushThicknessAndPath() - { - img.Draw(brush, thickness, path); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Equal(path, shapepath.Path); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsBrushThicknessPathAndOptions() - { - img.Draw(brush, thickness, path, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Equal(path, shapepath.Path); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsColorThicknessAndPath() - { - img.Draw(color, thickness, path); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Equal(path, shapepath.Path); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsColorThicknessPathAndOptions() - { - img.Draw(color, thickness, path, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Equal(path, shapepath.Path); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsPenAndPath() - { - img.Draw(pen, path); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Equal(path, shapepath.Path); - - Assert.Equal(pen, processor.Pen); - } - - [Fact] - public void CorrectlySetsPenPathAndOptions() - { - img.Draw(pen, path, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Equal(path, shapepath.Path); - - Assert.Equal(pen, processor.Pen); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPolygon.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPolygon.cs deleted file mode 100644 index 3474e6f62..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawPolygon.cs +++ /dev/null @@ -1,161 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Paths -{ - using System; - - using ImageSharp.Drawing.Brushes; - - using Xunit; - using ImageSharp.Drawing; - using System.Numerics; - using SixLabors.Shapes; - using ImageSharp.Drawing.Processors; - using ImageSharp.Drawing.Pens; - using ImageSharp.PixelFormats; - - public class DrawPolygon : IDisposable - { - float thickness = 7.2f; - GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - Pen pen = new Pen(Rgba32.Gray, 99.9f); - Vector2[] points = new Vector2[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - }; - private ProcessorWatchingImage img; - - public DrawPolygon() - { - this.img = new Paths.ProcessorWatchingImage(10, 10); - } - - public void Dispose() - { - img.Dispose(); - } - - [Fact] - public void CorrectlySetsBrushThicknessAndPoints() - { - img.DrawPolygon(brush, thickness, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - Polygon vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsBrushThicknessPointsAndOptions() - { - img.DrawPolygon(brush, thickness, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - Polygon vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsColorThicknessAndPoints() - { - img.DrawPolygon(color, thickness, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - Polygon vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsColorThicknessPointsAndOptions() - { - img.DrawPolygon(color, thickness, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - Polygon vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsPenAndPoints() - { - img.DrawPolygon(pen, points); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - Polygon vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Assert.Equal(pen, processor.Pen); - } - - [Fact] - public void CorrectlySetsPenPointsAndOptions() - { - img.DrawPolygon(pen, points, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath path = Assert.IsType(processor.Path); - - Polygon vector = Assert.IsType(path.Path); - LinearLineSegment segment = Assert.IsType(vector.LineSegments[0]); - - Assert.Equal(pen, processor.Pen); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawRectangle.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawRectangle.cs deleted file mode 100644 index e08e702c1..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawRectangle.cs +++ /dev/null @@ -1,177 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Paths -{ - using System; - using ImageSharp; - using ImageSharp.Drawing.Brushes; - using Xunit; - using ImageSharp.Drawing; - using ImageSharp.Drawing.Processors; - using ImageSharp.Drawing.Pens; - using ImageSharp.PixelFormats; - - public class DrawRectangle : IDisposable - { - float thickness = 7.2f; - GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - Pen pen = new Pen(Rgba32.Gray, 99.9f); - ImageSharp.Rectangle rectangle = new ImageSharp.Rectangle(10, 10, 98, 324); - - private ProcessorWatchingImage img; - - public DrawRectangle() - { - this.img = new Paths.ProcessorWatchingImage(10, 10); - } - - public void Dispose() - { - img.Dispose(); - } - - [Fact] - public void CorrectlySetsBrushThicknessAndRectangle() - { - img.Draw(brush, thickness, rectangle); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - SixLabors.Shapes.Rectangle rect = Assert.IsType(shapepath.Path); - - Assert.Equal(rect.Location.X, rectangle.X); - Assert.Equal(rect.Location.Y, rectangle.Y); - Assert.Equal(rect.Size.Width, rectangle.Width); - Assert.Equal(rect.Size.Height, rectangle.Height); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsBrushThicknessRectangleAndOptions() - { - img.Draw(brush, thickness, rectangle, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - - SixLabors.Shapes.Rectangle rect = Assert.IsType(shapepath.Path); - - Assert.Equal(rect.Location.X, rectangle.X); - Assert.Equal(rect.Location.Y, rectangle.Y); - Assert.Equal(rect.Size.Width, rectangle.Width); - Assert.Equal(rect.Size.Height, rectangle.Height); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - - [Fact] - public void CorrectlySetsColorThicknessAndRectangle() - { - img.Draw(color, thickness, rectangle); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - - SixLabors.Shapes.Rectangle rect = Assert.IsType(shapepath.Path); - - Assert.Equal(rect.Location.X, rectangle.X); - Assert.Equal(rect.Location.Y, rectangle.Y); - Assert.Equal(rect.Size.Width, rectangle.Width); - Assert.Equal(rect.Size.Height, rectangle.Height); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsColorThicknessRectangleAndOptions() - { - img.Draw(color, thickness, rectangle, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - - SixLabors.Shapes.Rectangle rect = Assert.IsType(shapepath.Path); - - Assert.Equal(rect.Location.X, rectangle.X); - Assert.Equal(rect.Location.Y, rectangle.Y); - Assert.Equal(rect.Size.Width, rectangle.Width); - Assert.Equal(rect.Size.Height, rectangle.Height); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - - [Fact] - public void CorrectlySetsPenAndRectangle() - { - img.Draw(pen, rectangle); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - - SixLabors.Shapes.Rectangle rect = Assert.IsType(shapepath.Path); - - Assert.Equal(rect.Location.X, rectangle.X); - Assert.Equal(rect.Location.Y, rectangle.Y); - Assert.Equal(rect.Size.Width, rectangle.Width); - Assert.Equal(rect.Size.Height, rectangle.Height); - - Assert.Equal(pen, processor.Pen); - } - - [Fact] - public void CorrectlySetsPenRectangleAndOptions() - { - img.Draw(pen, rectangle, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[0].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - - SixLabors.Shapes.Rectangle rect = Assert.IsType(shapepath.Path); - - Assert.Equal(rect.Location.X, rectangle.X); - Assert.Equal(rect.Location.Y, rectangle.Y); - Assert.Equal(rect.Size.Width, rectangle.Width); - Assert.Equal(rect.Size.Height, rectangle.Height); - - Assert.Equal(pen, processor.Pen); - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs index 494e2a672..78d49d35f 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/ShapePathTests.cs @@ -18,109 +18,6 @@ namespace ImageSharp.Tests.Drawing.Paths public class ShapePathTests { - private readonly Mock pathMock1; - private readonly Mock pathMock2; - private readonly SixLabors.Shapes.Rectangle bounds1; - - public ShapePathTests() - { - this.pathMock2 = new Mock(); - this.pathMock1 = new Mock(); - - this.bounds1 = new SixLabors.Shapes.Rectangle(10.5f, 10, 10, 10); - pathMock1.Setup(x => x.Bounds).Returns(this.bounds1); - pathMock2.Setup(x => x.Bounds).Returns(this.bounds1); - // wire up the 2 mocks to reference eachother - pathMock1.Setup(x => x.AsClosedPath()).Returns(() => pathMock2.Object); - } - - [Fact] - public void ShapePathFromPathConvertsBoundsDoesNotProxyToShape() - { - ShapePath region = new ShapePath(pathMock1.Object); - - Assert.Equal(Math.Floor(bounds1.Left), region.Bounds.Left); - Assert.Equal(Math.Ceiling(bounds1.Right), region.Bounds.Right); - - pathMock1.Verify(x => x.Bounds); - } - - [Fact] - public void ShapePathFromPathMaxIntersectionsProxyToShape() - { - ShapePath region = new ShapePath(pathMock1.Object); - - int i = region.MaxIntersections; - pathMock1.Verify(x => x.MaxIntersections); - } - - [Fact] - public void ShapePathFromPathScanXProxyToShape() - { - int xToScan = 10; - ShapePath region = new ShapePath(pathMock1.Object); - - pathMock1.Setup(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Callback((s, e, b, c, o) => { - Assert.Equal(xToScan, s.X); - Assert.Equal(xToScan, e.X); - Assert.True(s.Y < bounds1.Top); - Assert.True(e.Y > bounds1.Bottom); - }).Returns(0); - - int i = region.ScanX(xToScan, new float[0], 0, 0); - - pathMock1.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); - } - - [Fact] - public void ShapePathFromPathScanYProxyToShape() - { - int yToScan = 10; - ShapePath region = new ShapePath(pathMock1.Object); - - pathMock1.Setup(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Callback((s, e, b, c, o) => { - Assert.Equal(yToScan, s.Y); - Assert.Equal(yToScan, e.Y); - Assert.True(s.X < bounds1.Left); - Assert.True(e.X > bounds1.Right); - }).Returns(0); - - int i = region.ScanY(yToScan, new float[0], 0, 0); - - pathMock1.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); - } - - - [Fact] - public void ShapePathFromShapeScanXProxyToShape() - { - int xToScan = 10; - ShapePath region = new ShapePath(pathMock1.Object); - - pathMock1.Setup(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Callback((s, e, b, c, o) => { - Assert.Equal(xToScan, s.X); - Assert.Equal(xToScan, e.X); - Assert.True(s.Y < bounds1.Top); - Assert.True(e.Y > bounds1.Bottom); - }).Returns(0); - - int i = region.ScanX(xToScan, new float[0], 0, 0); - - pathMock1.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); - } - - [Fact] - public void GetPointInfoCallSinglePathForPath() - { - ShapePath region = new ShapePath(pathMock1.Object); - - ImageSharp.Drawing.PointInfo info = region.GetPointInfo(10, 1); - - pathMock1.Verify(x => x.Distance(new Vector2(10, 1)), Times.Once); - pathMock2.Verify(x => x.Distance(new Vector2(10, 1)), Times.Never); - } + // TODO readd these back in } } diff --git a/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs b/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs index 78c349233..6275ffd1c 100644 --- a/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Paths/ShapeRegionTests.cs @@ -81,7 +81,7 @@ namespace ImageSharp.Tests.Drawing.Paths Assert.True(e.X > bounds.Right); }).Returns(0); - int i = region.Scan(yToScan, new float[0], 0, 0); + int i = region.Scan(yToScan, new float[0]); pathMock.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } @@ -100,7 +100,7 @@ namespace ImageSharp.Tests.Drawing.Paths Assert.True(e.X > bounds.Right); }).Returns(0); - int i = region.Scan(yToScan, new float[0], 0, 0); + int i = region.Scan(yToScan, new float[0]); pathMock.Verify(x => x.FindIntersections(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs index 1516b33d4..4718ed419 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawText.cs @@ -136,7 +136,7 @@ namespace ImageSharp.Tests.Drawing.Text Assert.NotEmpty(this.img.ProcessorApplications); Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied - Assert.IsType>(this.img.ProcessorApplications[0].processor); + Assert.IsType>(this.img.ProcessorApplications[0].processor); } [Fact] @@ -146,7 +146,7 @@ namespace ImageSharp.Tests.Drawing.Text Assert.NotEmpty(this.img.ProcessorApplications); Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied - Assert.IsType>(this.img.ProcessorApplications[0].processor); + Assert.IsType>(this.img.ProcessorApplications[0].processor); } [Fact] @@ -156,7 +156,7 @@ namespace ImageSharp.Tests.Drawing.Text Assert.NotEmpty(this.img.ProcessorApplications); Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied - Assert.IsType>(this.img.ProcessorApplications[0].processor); + Assert.IsType>(this.img.ProcessorApplications[0].processor); } [Fact] @@ -166,7 +166,7 @@ namespace ImageSharp.Tests.Drawing.Text Assert.NotEmpty(this.img.ProcessorApplications); Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied - Assert.IsType>(this.img.ProcessorApplications[0].processor); + Assert.IsType>(this.img.ProcessorApplications[0].processor); } [Fact] @@ -207,7 +207,7 @@ namespace ImageSharp.Tests.Drawing.Text Assert.NotEmpty(this.img.ProcessorApplications); Assert.Equal(2, this.img.ProcessorApplications.Count); Assert.IsType>(this.img.ProcessorApplications[0].processor); - Assert.IsType>(this.img.ProcessorApplications[1].processor); + Assert.IsType>(this.img.ProcessorApplications[1].processor); } [Fact] @@ -218,7 +218,7 @@ namespace ImageSharp.Tests.Drawing.Text Assert.NotEmpty(this.img.ProcessorApplications); Assert.Equal(2, this.img.ProcessorApplications.Count); Assert.IsType>(this.img.ProcessorApplications[0].processor); - Assert.IsType>(this.img.ProcessorApplications[1].processor); + Assert.IsType>(this.img.ProcessorApplications[1].processor); } [Fact] From 0164f0b0a3901df1f4ace9838df0b34bbea51f44 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 30 May 2017 22:09:18 +0100 Subject: [PATCH 67/84] Fix Tests --- tests/ImageSharp.Tests/Drawing/BeziersTests.cs | 14 +++++++------- tests/ImageSharp.Tests/Drawing/DrawPathTests.cs | 4 ++-- tests/ImageSharp.Tests/Drawing/LineTests.cs | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs b/tests/ImageSharp.Tests/Drawing/BeziersTests.cs index ff6892199..3d49a70b8 100644 --- a/tests/ImageSharp.Tests/Drawing/BeziersTests.cs +++ b/tests/ImageSharp.Tests/Drawing/BeziersTests.cs @@ -43,8 +43,8 @@ namespace ImageSharp.Tests.Drawing Assert.Equal(Rgba32.HotPink, sourcePixels[138, 115]); //start points - Assert.Equal(Rgba32.HotPink, sourcePixels[10, 400]); - Assert.Equal(Rgba32.HotPink, sourcePixels[300, 400]); + Assert.Equal(Rgba32.HotPink, sourcePixels[10, 395]); + Assert.Equal(Rgba32.HotPink, sourcePixels[300, 395]); //curve points should not be never be set Assert.Equal(Rgba32.Blue, sourcePixels[30, 10]); @@ -85,14 +85,14 @@ namespace ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - //top of curve + // top of curve Assert.Equal(mergedColor, sourcePixels[138, 115]); - //start points - Assert.Equal(mergedColor, sourcePixels[10, 400]); - Assert.Equal(mergedColor, sourcePixels[300, 400]); + // start points + Assert.Equal(mergedColor, sourcePixels[10, 395]); + Assert.Equal(mergedColor, sourcePixels[300, 395]); - //curve points should not be never be set + // curve points should not be never be set Assert.Equal(Rgba32.Blue, sourcePixels[30, 10]); Assert.Equal(Rgba32.Blue, sourcePixels[240, 30]); diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs index 7d54879c3..a3911ac3e 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs @@ -43,7 +43,7 @@ namespace ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(Rgba32.HotPink, sourcePixels[9, 9]); + Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); @@ -89,7 +89,7 @@ namespace ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(mergedColor, sourcePixels[9, 9]); + Assert.Equal(mergedColor, sourcePixels[11, 11]); Assert.Equal(mergedColor, sourcePixels[199, 149]); diff --git a/tests/ImageSharp.Tests/Drawing/LineTests.cs b/tests/ImageSharp.Tests/Drawing/LineTests.cs index 3396d89c5..e751557b6 100644 --- a/tests/ImageSharp.Tests/Drawing/LineTests.cs +++ b/tests/ImageSharp.Tests/Drawing/LineTests.cs @@ -38,7 +38,7 @@ namespace ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(Rgba32.HotPink, sourcePixels[9, 9]); + Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); @@ -69,7 +69,7 @@ namespace ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(Rgba32.HotPink, sourcePixels[9, 9]); + Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); Assert.Equal(Rgba32.HotPink, sourcePixels[199, 149]); @@ -187,7 +187,7 @@ namespace ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(mergedColor, sourcePixels[9, 9]); + Assert.Equal(mergedColor, sourcePixels[11, 11]); Assert.Equal(mergedColor, sourcePixels[199, 149]); @@ -217,7 +217,7 @@ namespace ImageSharp.Tests.Drawing using (PixelAccessor sourcePixels = image.Lock()) { - Assert.Equal(Rgba32.HotPink, sourcePixels[8, 8]); + Assert.Equal(Rgba32.HotPink, sourcePixels[11, 11]); Assert.Equal(Rgba32.HotPink, sourcePixels[198, 10]); From 54a641ba2e6ca62a2bee00d5499575edba9c5ee9 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 30 May 2017 22:15:06 +0100 Subject: [PATCH 68/84] remove redundent code --- src/ImageSharp.Drawing/Pens/IPen.cs | 4 +- src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs | 21 +++------- .../Pens/Processors/ColoredPointInfo.cs | 27 ------------- .../Pens/Processors/PenApplicator.cs | 40 ------------------- 4 files changed, 8 insertions(+), 84 deletions(-) delete mode 100644 src/ImageSharp.Drawing/Pens/Processors/ColoredPointInfo.cs delete mode 100644 src/ImageSharp.Drawing/Pens/Processors/PenApplicator.cs diff --git a/src/ImageSharp.Drawing/Pens/IPen.cs b/src/ImageSharp.Drawing/Pens/IPen.cs index affcb9d1f..20ac53daf 100644 --- a/src/ImageSharp.Drawing/Pens/IPen.cs +++ b/src/ImageSharp.Drawing/Pens/IPen.cs @@ -16,9 +16,9 @@ namespace ImageSharp.Drawing.Pens where TPixel : struct, IPixel { /// - /// Gets the stoke fill. + /// Gets the stroke fill. /// - IBrush StokeFill { get; } + IBrush StrokeFill { get; } } /// diff --git a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs index 0a0c81f9c..65ec9eabf 100644 --- a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs +++ b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs @@ -27,8 +27,8 @@ namespace ImageSharp.Drawing.Pens public class Pen : IPen where TPixel : struct, IPixel { - private static readonly float[] EmptyPattern = new float[0]; - private readonly float[] pattern; + private static readonly ReadOnlySpan EmptyPattern = new float[0]; + private readonly ReadOnlySpan pattern; /// /// Initializes a new instance of the class. @@ -36,7 +36,7 @@ namespace ImageSharp.Drawing.Pens /// The color. /// The width. /// The pattern. - public Pen(TPixel color, float width, float[] pattern) + public Pen(TPixel color, float width, ReadOnlySpan pattern) : this(new SolidBrush(color), width, pattern) { } @@ -47,9 +47,9 @@ namespace ImageSharp.Drawing.Pens /// The brush. /// The width. /// The pattern. - public Pen(IBrush brush, float width, float[] pattern) + public Pen(IBrush brush, float width, ReadOnlySpan pattern) { - this.StokeFill = brush; + this.StrokeFill = brush; this.StrokeWidth = width; this.pattern = pattern; } @@ -74,17 +74,8 @@ namespace ImageSharp.Drawing.Pens { } - /// - /// Initializes a new instance of the class. - /// - /// The pen. - internal Pen(Pen pen) - : this(pen.StokeFill, pen.StrokeWidth, pen.pattern) - { - } - /// - public IBrush StokeFill { get; } + public IBrush StrokeFill { get; } /// public float StrokeWidth { get; } diff --git a/src/ImageSharp.Drawing/Pens/Processors/ColoredPointInfo.cs b/src/ImageSharp.Drawing/Pens/Processors/ColoredPointInfo.cs deleted file mode 100644 index 65a8a6131..000000000 --- a/src/ImageSharp.Drawing/Pens/Processors/ColoredPointInfo.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Drawing.Processors -{ - using ImageSharp.PixelFormats; - - /// - /// Returns details about how far away from the inside of a shape and the color the pixel could be. - /// - /// The type of the color. - public struct ColoredPointInfo - where TPixel : struct, IPixel - { - /// - /// The color - /// - public TPixel Color; - - /// - /// The distance from element - /// - public float DistanceFromElement; - } -} diff --git a/src/ImageSharp.Drawing/Pens/Processors/PenApplicator.cs b/src/ImageSharp.Drawing/Pens/Processors/PenApplicator.cs deleted file mode 100644 index ac1889068..000000000 --- a/src/ImageSharp.Drawing/Pens/Processors/PenApplicator.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Drawing.Processors -{ - using System; - using ImageSharp.PixelFormats; - - /// - /// primitive that converts a into a color and a distance away from the drawable part of the path. - /// - /// The type of the color. - public abstract class PenApplicator : IDisposable - where TPixel : struct, IPixel - { - /// - /// Gets the required region. - /// - /// - /// The required region. - /// - public abstract RectangleF RequiredRegion { get; } - - /// - public abstract void Dispose(); - - /// - /// Gets a from a point represented by a . - /// - /// The x. - /// The y. - /// The information to extract color details about. - /// - /// Returns the color details and distance from a solid bit of the line. - /// - public abstract ColoredPointInfo GetColor(int x, int y, PointInfo info); - } -} From 230e47991f786bc579821b31cf1e0a4689a8befa Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 30 May 2017 22:54:04 +0100 Subject: [PATCH 69/84] migrate text glyph rendering to SixLabors.Shapes.Text --- .../ImageSharp.Drawing.csproj | 3 +- .../Paths/DrawPathCollection.cs | 115 ++++++++++++++++ .../Paths/FillPathCollection.cs | 81 +++++++++++ src/ImageSharp.Drawing/Text/DrawText.cs | 26 ++-- src/ImageSharp.Drawing/Text/GlyphBuilder.cs | 127 ------------------ .../Text/TextGraphicsOptions.cs | 13 +- .../Drawing/Text/GlyphBuilder.cs | 68 ---------- 7 files changed, 215 insertions(+), 218 deletions(-) create mode 100644 src/ImageSharp.Drawing/Paths/DrawPathCollection.cs create mode 100644 src/ImageSharp.Drawing/Paths/FillPathCollection.cs delete mode 100644 src/ImageSharp.Drawing/Text/GlyphBuilder.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Text/GlyphBuilder.cs diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index a3552a09c..a9afe37f8 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -36,11 +36,10 @@ + All - - ..\..\ImageSharp.ruleset diff --git a/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs b/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs new file mode 100644 index 000000000..5cb499415 --- /dev/null +++ b/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs @@ -0,0 +1,115 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using Drawing; + using Drawing.Brushes; + using Drawing.Pens; + using ImageSharp.PixelFormats; + using SixLabors.Shapes; + + /// + /// Extension methods for the type. + /// + public static partial class ImageExtensions + { + /// + /// Draws the outline of the polygon with the provided pen. + /// + /// The type of the color. + /// The image this method extends. + /// The pen. + /// The paths. + /// The options. + /// The . + public static Image Draw(this Image source, IPen pen, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + foreach (IPath path in paths) + { + source.Draw(pen, new ShapePath(path), options); + } + + return source; + } + + /// + /// Draws the outline of the polygon with the provided pen. + /// + /// The type of the color. + /// The image this method extends. + /// The pen. + /// The paths. + /// The . + public static Image Draw(this Image source, IPen pen, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Draw(pen, paths, GraphicsOptions.Default); + } + + /// + /// Draws the outline of the polygon with the provided brush at the provided thickness. + /// + /// The type of the color. + /// The image this method extends. + /// The brush. + /// The thickness. + /// The shapes. + /// The options. + /// The . + public static Image Draw(this Image source, IBrush brush, float thickness, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + return source.Draw(new Pen(brush, thickness), paths, options); + } + + /// + /// Draws the outline of the polygon with the provided brush at the provided thickness. + /// + /// The type of the color. + /// The image this method extends. + /// The brush. + /// The thickness. + /// The paths. + /// The . + public static Image Draw(this Image source, IBrush brush, float thickness, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Draw(new Pen(brush, thickness), paths); + } + + /// + /// Draws the outline of the polygon with the provided brush at the provided thickness. + /// + /// The type of the color. + /// The image this method extends. + /// The color. + /// The thickness. + /// The paths. + /// The options. + /// The . + public static Image Draw(this Image source, TPixel color, float thickness, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + return source.Draw(new SolidBrush(color), thickness, paths, options); + } + + /// + /// Draws the outline of the polygon with the provided brush at the provided thickness. + /// + /// The type of the color. + /// The image this method extends. + /// The color. + /// The thickness. + /// The paths. + /// The . + public static Image Draw(this Image source, TPixel color, float thickness, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Draw(new SolidBrush(color), thickness, paths); + } + } +} diff --git a/src/ImageSharp.Drawing/Paths/FillPathCollection.cs b/src/ImageSharp.Drawing/Paths/FillPathCollection.cs new file mode 100644 index 000000000..3ea9fb94b --- /dev/null +++ b/src/ImageSharp.Drawing/Paths/FillPathCollection.cs @@ -0,0 +1,81 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using Drawing; + using Drawing.Brushes; + using ImageSharp.PixelFormats; + using SixLabors.Shapes; + + /// + /// Extension methods for the type. + /// + public static partial class ImageExtensions + { + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush.. + /// + /// The type of the color. + /// The image this method extends. + /// The brush. + /// The shapes. + /// The graphics options. + /// The . + public static Image Fill(this Image source, IBrush brush, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + foreach (IPath s in paths) + { + source.Fill(brush, s, options); + } + + return source; + } + + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush. + /// + /// The type of the color. + /// The image this method extends. + /// The brush. + /// The paths. + /// The . + public static Image Fill(this Image source, IBrush brush, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Fill(brush, paths, GraphicsOptions.Default); + } + + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush.. + /// + /// The type of the color. + /// The image this method extends. + /// The color. + /// The paths. + /// The options. + /// The . + public static Image Fill(this Image source, TPixel color, IPathCollection paths, GraphicsOptions options) + where TPixel : struct, IPixel + { + return source.Fill(new SolidBrush(color), paths, options); + } + + /// + /// Flood fills the image in the shape of the provided polygon with the specified brush.. + /// + /// The type of the color. + /// The image this method extends. + /// The color. + /// The paths. + /// The . + public static Image Fill(this Image source, TPixel color, IPathCollection paths) + where TPixel : struct, IPixel + { + return source.Fill(new SolidBrush(color), paths); + } + } +} diff --git a/src/ImageSharp.Drawing/Text/DrawText.cs b/src/ImageSharp.Drawing/Text/DrawText.cs index bd33289fa..6bb87dcf5 100644 --- a/src/ImageSharp.Drawing/Text/DrawText.cs +++ b/src/ImageSharp.Drawing/Text/DrawText.cs @@ -12,6 +12,7 @@ namespace ImageSharp using Drawing.Pens; using ImageSharp.PixelFormats; using SixLabors.Fonts; + using SixLabors.Shapes; /// /// Extension methods for the type. @@ -167,43 +168,32 @@ namespace ImageSharp public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPen pen, Vector2 location, TextGraphicsOptions options) where TPixel : struct, IPixel { - GlyphBuilder glyphBuilder = new GlyphBuilder(location); - - TextRenderer renderer = new TextRenderer(glyphBuilder); - Vector2 dpi = DefaultTextDpi; if (options.UseImageResolution) { dpi = new Vector2((float)source.MetaData.HorizontalResolution, (float)source.MetaData.VerticalResolution); } - FontSpan style = new FontSpan(font, dpi) + var style = new FontSpan(font, dpi) { ApplyKerning = options.ApplyKerning, TabWidth = options.TabWidth, WrappingWidth = options.WrapTextWidth, - Alignment = options.TextAlignment + HorizontalAlignment = options.HorizontalAlignment, + VerticalAlignment = options.VerticalAlignment }; - renderer.RenderText(text, style); - - System.Collections.Generic.IEnumerable shapesToDraw = glyphBuilder.Paths; + IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, style).Translate(location); // todo move to better API - GraphicsOptions pathOptions = (GraphicsOptions)options; + var pathOptions = (GraphicsOptions)options; if (brush != null) { - foreach (SixLabors.Shapes.IPath s in shapesToDraw) - { - source.Fill(brush, s, pathOptions); - } + source.Fill(brush, glyphs, pathOptions); } if (pen != null) { - foreach (SixLabors.Shapes.IPath s in shapesToDraw) - { - source.Draw(pen, s, pathOptions); - } + source.Draw(pen, glyphs, pathOptions); } return source; diff --git a/src/ImageSharp.Drawing/Text/GlyphBuilder.cs b/src/ImageSharp.Drawing/Text/GlyphBuilder.cs deleted file mode 100644 index 0033a608c..000000000 --- a/src/ImageSharp.Drawing/Text/GlyphBuilder.cs +++ /dev/null @@ -1,127 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Drawing -{ - using System.Collections.Generic; - using System.Numerics; - - using SixLabors.Fonts; - using SixLabors.Shapes; - - /// - /// rendering surface that Fonts can use to generate Shapes. - /// - internal class GlyphBuilder : IGlyphRenderer - { - private readonly PathBuilder builder = new PathBuilder(); - private readonly List paths = new List(); - private Vector2 currentPoint = default(Vector2); - - /// - /// Initializes a new instance of the class. - /// - public GlyphBuilder() - : this(Vector2.Zero) - { - // glyphs are renderd realative to bottom left so invert the Y axis to allow it to render on top left origin surface - this.builder = new PathBuilder(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The origin. - public GlyphBuilder(Vector2 origin) - { - this.builder = new PathBuilder(); - this.builder.SetOrigin(origin); - } - - /// - /// Gets the paths that have been rendered by this. - /// - public IEnumerable Paths => this.paths; - - /// - /// Begins the glyph. - /// - /// The offset that the glyph will be rendered at. - void IGlyphRenderer.BeginGlyph(Vector2 location) - { - this.builder.Clear(); - } - - /// - /// Begins the figure. - /// - void IGlyphRenderer.BeginFigure() - { - this.builder.StartFigure(); - } - - /// - /// Draws a cubic bezier from the current point to the - /// - /// The second control point. - /// The third control point. - /// The point. - void IGlyphRenderer.CubicBezierTo(Vector2 secondControlPoint, Vector2 thirdControlPoint, Vector2 point) - { - this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); - this.currentPoint = point; - } - - /// - /// Ends the glyph. - /// - void IGlyphRenderer.EndGlyph() - { - this.paths.Add(this.builder.Build()); - } - - /// - /// Ends the figure. - /// - void IGlyphRenderer.EndFigure() - { - this.builder.CloseFigure(); - } - - /// - /// Draws a line from the current point to the . - /// - /// The point. - void IGlyphRenderer.LineTo(Vector2 point) - { - this.builder.AddLine(this.currentPoint, point); - this.currentPoint = point; - } - - /// - /// Moves to current point to the supplied vector. - /// - /// The point. - void IGlyphRenderer.MoveTo(Vector2 point) - { - this.builder.StartFigure(); - this.currentPoint = point; - } - - /// - /// Draws a quadratics bezier from the current point to the - /// - /// The second control point. - /// The point. - void IGlyphRenderer.QuadraticBezierTo(Vector2 secondControlPoint, Vector2 point) - { - Vector2 c1 = (((secondControlPoint - this.currentPoint) * 2) / 3) + this.currentPoint; - Vector2 c2 = (((secondControlPoint - point) * 2) / 3) + point; - - this.builder.AddBezier(this.currentPoint, c1, c2, point); - this.currentPoint = point; - } - } -} diff --git a/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs b/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs index 388b39bcc..593ac36d4 100644 --- a/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs +++ b/src/ImageSharp.Drawing/Text/TextGraphicsOptions.cs @@ -33,7 +33,8 @@ namespace ImageSharp.Drawing private float wrapTextWidth; - private SixLabors.Fonts.TextAlignment? textAlignment; + private SixLabors.Fonts.HorizontalAlignment? horizontalAlignment; + private SixLabors.Fonts.VerticalAlignment? verticalAlignment; /// /// Initializes a new instance of the struct. @@ -45,7 +46,8 @@ namespace ImageSharp.Drawing this.tabWidth = 4; this.useImageResolution = false; this.wrapTextWidth = 0; - this.textAlignment = SixLabors.Fonts.TextAlignment.Left; + this.horizontalAlignment = HorizontalAlignment.Left; + this.verticalAlignment = VerticalAlignment.Top; this.antialiasSubpixelDepth = 16; this.blenderMode = PixelBlenderMode.Normal; @@ -104,7 +106,12 @@ namespace ImageSharp.Drawing /// defined by the location and width, if equals zero, and thus /// wrapping disabled, then the alignment is relative to the drawing location. /// - public TextAlignment TextAlignment { get => this.textAlignment ?? TextAlignment.Left; set => this.textAlignment = value; } + public HorizontalAlignment HorizontalAlignment { get => this.horizontalAlignment ?? HorizontalAlignment.Left; set => this.horizontalAlignment = value; } + + /// + /// Gets or sets a value indicating how to align the text relative to the rendering space. + /// + public VerticalAlignment VerticalAlignment { get => this.verticalAlignment ?? VerticalAlignment.Top; set => this.verticalAlignment = value; } /// /// Performs an implicit conversion from to . diff --git a/tests/ImageSharp.Tests/Drawing/Text/GlyphBuilder.cs b/tests/ImageSharp.Tests/Drawing/Text/GlyphBuilder.cs deleted file mode 100644 index 7f16f30bb..000000000 --- a/tests/ImageSharp.Tests/Drawing/Text/GlyphBuilder.cs +++ /dev/null @@ -1,68 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Text -{ - using ImageSharp.Drawing; - using SixLabors.Fonts; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Numerics; - using System.Threading.Tasks; - using Xunit; - - public class GlyphBuilderTests - { - [Fact] - public void OriginUsed() - { - // Y axis is inverted as it expects to be drawing for bottom left - GlyphBuilder fullBuilder = new GlyphBuilder(new System.Numerics.Vector2(10, 99)); - IGlyphRenderer builder = fullBuilder; - - builder.BeginGlyph(Vector2.Zero); - builder.BeginFigure(); - builder.MoveTo(new Vector2(0, 0)); - builder.LineTo(new Vector2(0, 10)); // becomes 0, -10 - - builder.CubicBezierTo( - new Vector2(15, 15), // control point - will not be in the final point collection - new Vector2(15, 10), // control point - will not be in the final point collection - new Vector2(10, 10));// becomes 10, -10 - - builder.QuadraticBezierTo( - new Vector2(10, 5), // control point - will not be in the final point collection - new Vector2(10, 0)); - - builder.EndFigure(); - builder.EndGlyph(); - - System.Collections.Immutable.ImmutableArray points = fullBuilder.Paths.Single().Flatten().Single().Points; - - Assert.Contains(new Vector2(10, 99), points); - Assert.Contains(new Vector2(10, 109), points); - Assert.Contains(new Vector2(20, 99), points); - Assert.Contains(new Vector2(20, 109), points); - } - - [Fact] - public void EachGlypeCausesNewPath() - { - // Y axis is inverted as it expects to be drawing for bottom left - GlyphBuilder fullBuilder = new GlyphBuilder(); - IGlyphRenderer builder = fullBuilder; - for (int i = 0; i < 10; i++) - { - builder.BeginGlyph(Vector2.Zero); - builder.BeginFigure(); - builder.MoveTo(new Vector2(0, 0)); - builder.LineTo(new Vector2(0, 10)); // becomes 0, -10 - builder.LineTo(new Vector2(10, 10));// becomes 10, -10 - builder.LineTo(new Vector2(10, 0)); - builder.EndFigure(); - builder.EndGlyph(); - } - - Assert.Equal(10, fullBuilder.Paths.Count()); - } - } -} From ba24d42d448d678fc22bfa76c2eeb54d39dc8795 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 30 May 2017 23:04:36 +0100 Subject: [PATCH 70/84] fix property accessor --- src/ImageSharp.Drawing/Paths/DrawPath.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp.Drawing/Paths/DrawPath.cs b/src/ImageSharp.Drawing/Paths/DrawPath.cs index eb12a2606..1fba06370 100644 --- a/src/ImageSharp.Drawing/Paths/DrawPath.cs +++ b/src/ImageSharp.Drawing/Paths/DrawPath.cs @@ -28,7 +28,7 @@ namespace ImageSharp public static Image Draw(this Image source, IPen pen, IPath path, GraphicsOptions options) where TPixel : struct, IPixel { - return source.Fill(pen.StokeFill, new ShapePath(path, pen), options); + return source.Fill(pen.StrokeFill, new ShapePath(path, pen), options); } /// From 1e4d1df2c1abf36993bcb1c1d52837be75e10dab Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 31 May 2017 09:34:50 +1000 Subject: [PATCH 71/84] Use EnsureProcessorChangesAreConstrained --- tests/ImageSharp.Tests/ImageComparer.cs | 34 ++++++++++++++++++- .../Binarization/BinaryThresholdTest.cs | 5 +-- .../Processing/Binarization/DitherTest.cs | 12 ++----- .../Processing/ColorMatrix/BlackWhiteTest.cs | 5 +-- .../ColorMatrix/ColorBlindnessTest.cs | 5 +-- .../Processing/ColorMatrix/GrayscaleTest.cs | 5 +-- .../Processing/ColorMatrix/HueTest.cs | 5 +-- .../Processing/ColorMatrix/KodachromeTest.cs | 5 +-- .../Processing/ColorMatrix/LomographTest.cs | 5 +-- .../Processing/ColorMatrix/PolaroidTest.cs | 5 +-- .../Processing/ColorMatrix/SaturationTest.cs | 5 +-- .../Processing/ColorMatrix/SepiaTest.cs | 5 +-- .../Processing/Convolution/BoxBlurTest.cs | 5 +-- .../Processing/Convolution/DetectEdgesTest.cs | 5 +-- .../Convolution/GaussianBlurTest.cs | 5 +-- .../Convolution/GaussianSharpenTest.cs | 5 +-- .../Processing/Effects/AlphaTest.cs | 5 +-- .../Processing/Effects/BackgroundColorTest.cs | 5 +-- .../Processing/Effects/BrightnessTest.cs | 5 +-- .../Processing/Effects/ContrastTest.cs | 5 +-- .../Processing/Effects/InvertTest.cs | 5 +-- .../Processing/Effects/OilPaintTest.cs | 7 +--- .../Processing/Effects/PixelateTest.cs | 2 ++ .../Processing/Overlays/GlowTest.cs | 5 +-- .../Processing/Overlays/VignetteTest.cs | 5 +-- 25 files changed, 60 insertions(+), 100 deletions(-) diff --git a/tests/ImageSharp.Tests/ImageComparer.cs b/tests/ImageSharp.Tests/ImageComparer.cs index 3e40cc2d7..9a30cc363 100644 --- a/tests/ImageSharp.Tests/ImageComparer.cs +++ b/tests/ImageSharp.Tests/ImageComparer.cs @@ -21,6 +21,38 @@ namespace ImageSharp.Tests const int DefaultSegmentThreshold = 3; // The greyscale difference between 2 segements my be > 3 before it influences the overall difference const float DefaultImageThreshold = 0.000F; // After segment thresholds the images must have no differences + /// + /// Fills the bounded area with a solid color and does a visual comparison between 2 images asserting the difference outwith + /// that area is less then a configurable threshold. + /// + /// The color of the expected image + /// The color type fo the the actual image + /// The expected image + /// The actual image + /// The bounds within the image has been altered + /// + /// The threshold for the percentage difference where the images are asumed to be the same. + /// The default/undefined value is + /// + /// + /// The threshold of the individual segments before it acumulates towards the overall difference. + /// The default undefined value is + /// + /// + /// This is a sampling factor we sample a grid of average pixels width by high + /// The default undefined value is + /// + public static void EnsureProcessorChangesAreConstrained(Image expected, Image actual, Rectangle bounds, float imageTheshold = DefaultImageThreshold, byte segmentThreshold = DefaultSegmentThreshold, int scalingFactor = DefaultScalingFactor) + where TPixelA : struct, IPixel + where TPixelB : struct, IPixel + { + // Draw identical shapes over the bounded and compare to ensure changes are constrained. + expected.Fill(NamedColors.HotPink, bounds); + actual.Fill(NamedColors.HotPink, bounds); + + CheckSimilarity(expected, actual, imageTheshold, segmentThreshold, scalingFactor); + } + /// /// Does a visual comparison between 2 images and then asserts the difference is less then a configurable threshold /// @@ -64,7 +96,7 @@ namespace ImageSharp.Tests /// This is a sampling factor we sample a grid of average pixels width by high /// The default undefined value is /// - /// Returns a number from 0 - 1 which represents the diference focter between the images. + /// Returns a number from 0 - 1 which represents the difference focter between the images. public static float PercentageDifference(this Image source, Image target, byte segmentThreshold = DefaultSegmentThreshold, int scalingFactor = DefaultScalingFactor) where TPixelA : struct, IPixel where TPixelB : struct, IPixel diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs index 967844004..f9a5a9628 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs @@ -44,10 +44,7 @@ namespace ImageSharp.Tests.Processing.Binarization image.BinaryThreshold(value, bounds) .DebugSave(provider, value, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs index 92f685dfa..f5227e7d0 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageSharp.Tests +namespace ImageSharp.Tests.Processing.Binarization { using ImageSharp.Dithering; using ImageSharp.Dithering.Ordered; @@ -56,10 +56,7 @@ namespace ImageSharp.Tests image.Dither(ditherer, bounds) .DebugSave(provider, name, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } @@ -88,10 +85,7 @@ namespace ImageSharp.Tests image.Dither(diffuser,.5F, bounds) .DebugSave(provider, name, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs index 066b392d7..73847ae3a 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs @@ -36,10 +36,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix image.BlackWhite(bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs index 314b405c2..6d144fdae 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs @@ -50,10 +50,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix image.ColorBlindness(colorBlindness, bounds) .DebugSave(provider, colorBlindness.ToString(), Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs index f0a23429d..11d53a4c7 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs @@ -54,10 +54,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix image.Grayscale(value, bounds) .DebugSave(provider, value.ToString()); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs index a102adb92..e7dffe74a 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs @@ -43,10 +43,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix image.Hue(value, bounds) .DebugSave(provider, value, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs index 2824d8fd2..2da4e9fea 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs @@ -36,10 +36,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix image.Kodachrome(bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs index 146af1652..629d9793a 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs @@ -38,10 +38,7 @@ namespace ImageSharp.Tests image.Lomograph(bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs index 4304f3b45..b66589f4d 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs @@ -36,10 +36,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix image.Polaroid(bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs index fcc9656f3..66c92262d 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs @@ -43,10 +43,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix image.Saturation(value, bounds) .DebugSave(provider, value, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs index 47eaa874e..5a54235fa 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs @@ -36,10 +36,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix image.Sepia(bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs index e171dca99..cbcdd6b49 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs @@ -43,10 +43,7 @@ namespace ImageSharp.Tests.Processing.Convolution image.BoxBlur(value, bounds) .DebugSave(provider, value, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs index b03afdb22..880c5beae 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs @@ -52,10 +52,7 @@ namespace ImageSharp.Tests.Processing.Convolution image.DetectEdges(detector, bounds) .DebugSave(provider, detector.ToString(), Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs index d91e4089e..01b56dec8 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs @@ -43,10 +43,7 @@ namespace ImageSharp.Tests.Processing.Convolution image.GaussianBlur(value, bounds) .DebugSave(provider, value, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs index 30bb44a67..f0ac37e1b 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs @@ -43,10 +43,7 @@ namespace ImageSharp.Tests.Processing.Convolution image.GaussianSharpen(value, bounds) .DebugSave(provider, value, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs b/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs index a25e48ac3..737076270 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs @@ -43,10 +43,7 @@ namespace ImageSharp.Tests.Processing.Effects image.Alpha(value, bounds) .DebugSave(provider, value, Extensions.Png); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs b/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs index fd56dd6e7..97e6471f8 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs @@ -36,10 +36,7 @@ namespace ImageSharp.Tests.Processing.Effects image.BackgroundColor(NamedColors.HotPink, bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs b/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs index 38c374635..580b18187 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs @@ -43,10 +43,7 @@ namespace ImageSharp.Tests.Processing.Effects image.Brightness(value, bounds) .DebugSave(provider, value, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); ; } } } diff --git a/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs b/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs index 837cf8057..3003e9ddc 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs @@ -43,10 +43,7 @@ namespace ImageSharp.Tests.Processing.Effects image.Contrast(value, bounds) .DebugSave(provider, value, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs b/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs index af2ac1edb..8ad36e54c 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs @@ -36,10 +36,7 @@ namespace ImageSharp.Tests.Processing.Effects image.Invert(bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs b/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs index 3d4725f88..de9bf583d 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs @@ -43,12 +43,7 @@ namespace ImageSharp.Tests image.OilPaint(levels, brushSize, bounds) .DebugSave(provider, string.Join("-", levels, brushSize), Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - - // TODO: Why does the png box fail without the additional parameter. - ImageComparer.CheckSimilarity(source, image, 0.001F); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds, 0.001F); } } } diff --git a/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs b/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs index d52b7a290..d7cff18c3 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs @@ -76,6 +76,8 @@ namespace ImageSharp.Tests.Processing.Effects Assert.Equal(sourceColor, image[tx, ty]); } } + + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs b/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs index 0a94659bb..0c4ad72ee 100644 --- a/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs +++ b/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs @@ -60,10 +60,7 @@ namespace ImageSharp.Tests.Processing.Overlays image.Glow(bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } diff --git a/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs b/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs index 7a566a1b3..583331bad 100644 --- a/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs +++ b/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs @@ -60,10 +60,7 @@ namespace ImageSharp.Tests.Processing.Overlays image.Vignette(bounds) .DebugSave(provider, null, Extensions.Bmp); - // Draw identical shapes over the bounded and compare to ensure changes are constrained. - image.Fill(NamedColors.HotPink, bounds); - source.Fill(NamedColors.HotPink, bounds); - ImageComparer.CheckSimilarity(image, source); + ImageComparer.EnsureProcessorChangesAreConstrained(source, image, bounds); } } } From 5fa10c0ab38c6a9e67e0e9e2edd200455630c923 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 31 May 2017 09:49:39 +1000 Subject: [PATCH 72/84] Remove StandardImageClass --- .../ImageSharp.Tests/Drawing/BlendedShapes.cs | 4 ++-- .../ImageSharp.Tests/Drawing/DrawImageTest.cs | 2 +- tests/ImageSharp.Tests/FileTestBase.cs | 2 +- .../Formats/GeneralFormatTests.cs | 2 +- .../Formats/Gif/GifDecoderTests.cs | 2 +- .../Formats/Gif/GifEncoderTests.cs | 2 +- .../Formats/Jpg/JpegDecoderTests.cs | 16 +++++++------- .../Formats/Jpg/JpegEncoderTests.cs | 12 +++++----- .../Formats/Jpg/JpegProfilingBenchmarks.cs | 2 +- .../Formats/Jpg/JpegUtilsTests.cs | 4 ++-- .../Formats/Png/PngDecoderTests.cs | 2 +- .../Formats/Png/PngEncoderTests.cs | 2 +- .../Formats/Png/PngSmokeTests.cs | 6 ++--- .../Binarization/BinaryThresholdTest.cs | 4 ++-- .../Processing/Binarization/DitherTest.cs | 8 +++---- .../Processing/ColorMatrix/BlackWhiteTest.cs | 4 ++-- .../ColorMatrix/ColorBlindnessTest.cs | 4 ++-- .../Processing/ColorMatrix/GrayscaleTest.cs | 4 ++-- .../Processing/ColorMatrix/HueTest.cs | 4 ++-- .../Processing/ColorMatrix/KodachromeTest.cs | 4 ++-- .../Processing/ColorMatrix/LomographTest.cs | 4 ++-- .../Processing/ColorMatrix/PolaroidTest.cs | 4 ++-- .../Processing/ColorMatrix/SaturationTest.cs | 4 ++-- .../Processing/ColorMatrix/SepiaTest.cs | 4 ++-- .../Processing/Convolution/BoxBlurTest.cs | 4 ++-- .../Processing/Convolution/DetectEdgesTest.cs | 4 ++-- .../Convolution/GaussianBlurTest.cs | 4 ++-- .../Convolution/GaussianSharpenTest.cs | 4 ++-- .../Processing/Effects/AlphaTest.cs | 4 ++-- .../Processing/Effects/BackgroundColorTest.cs | 4 ++-- .../Processing/Effects/BrightnessTest.cs | 4 ++-- .../Processing/Effects/ContrastTest.cs | 4 ++-- .../Processing/Effects/InvertTest.cs | 4 ++-- .../Processing/Effects/OilPaintTest.cs | 4 ++-- .../Processing/Effects/PixelateTest.cs | 4 ++-- .../Processing/Overlays/GlowTest.cs | 8 +++---- .../Processing/Overlays/VignetteTest.cs | 8 +++---- .../Processing/Transforms/AutoOrientTests.cs | 2 +- .../Processing/Transforms/CropTest.cs | 2 +- .../Processing/Transforms/EntropyCropTest.cs | 2 +- .../Processing/Transforms/FlipTests.cs | 2 +- .../Processing/Transforms/PadTest.cs | 2 +- .../Processing/Transforms/ResizeTests.cs | 22 +++++++++---------- .../Processing/Transforms/RotateFlipTests.cs | 2 +- .../Processing/Transforms/RotateTests.cs | 4 ++-- .../Processing/Transforms/SkewTest.cs | 2 +- .../ImageProviders/FileProvider.cs | 2 +- .../ImageProviders/TestImageProvider.cs | 4 ++-- .../TestUtilities/PixelTypes.cs | 5 ----- .../TestUtilities/TestUtilityExtensions.cs | 3 +-- .../Tests/TestImageProviderTests.cs | 8 +++---- .../Tests/TestUtilityExtensionsTests.cs | 8 +++---- 52 files changed, 115 insertions(+), 121 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/BlendedShapes.cs b/tests/ImageSharp.Tests/Drawing/BlendedShapes.cs index 6c742c2e0..23f0569e7 100644 --- a/tests/ImageSharp.Tests/Drawing/BlendedShapes.cs +++ b/tests/ImageSharp.Tests/Drawing/BlendedShapes.cs @@ -18,7 +18,7 @@ namespace ImageSharp.Tests.Drawing .Select(x=> new object[] { x }); [Theory] - [WithBlankImages(nameof(modes), 100, 100, PixelTypes.StandardImageClass)] + [WithBlankImages(nameof(modes), 100, 100, PixelTypes.Rgba32)] public void DrawBlendedValues(TestImageProvider provider, PixelBlenderMode mode) where TPixel : struct, IPixel { @@ -34,7 +34,7 @@ namespace ImageSharp.Tests.Drawing } [Theory] - [WithBlankImages(nameof(modes), 100, 100, PixelTypes.StandardImageClass)] + [WithBlankImages(nameof(modes), 100, 100, PixelTypes.Rgba32)] public void DrawBlendedValues_transparent(TestImageProvider provider, PixelBlenderMode mode) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs index 030034a8f..42353a2aa 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawImageTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests public class DrawImageTest : FileTestBase { - private const PixelTypes PixelTypes = Tests.PixelTypes.StandardImageClass; + private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32; public static readonly string[] TestFiles = { TestImages.Jpeg.Baseline.Calliphora, diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs index ff0801e8a..51a1562f5 100644 --- a/tests/ImageSharp.Tests/FileTestBase.cs +++ b/tests/ImageSharp.Tests/FileTestBase.cs @@ -47,7 +47,7 @@ namespace ImageSharp.Tests /// /// The standard pixel format enumeration /// - public const PixelTypes StandardPixelType = PixelTypes.StandardImageClass; + public const PixelTypes DefaultPixelType = PixelTypes.Rgba32; public static class Extensions { diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index 411cc600a..ec1a8c465 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -14,7 +14,7 @@ namespace ImageSharp.Tests public class GeneralFormatTests : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ResolutionShouldChange(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index a5fc92901..89df2d086 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -14,7 +14,7 @@ namespace ImageSharp.Tests public class GifDecoderTests { - private const PixelTypes PixelTypes = Tests.PixelTypes.StandardImageClass | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; + private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; public static readonly string[] TestFiles = { TestImages.Gif.Giphy, TestImages.Gif.Rings, TestImages.Gif.Trans }; diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index b0ffaaf85..70cc8e2ba 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -13,7 +13,7 @@ namespace ImageSharp.Tests public class GifEncoderTests { - private const PixelTypes PixelTypes = Tests.PixelTypes.StandardImageClass | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; + private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; [Theory] [WithTestPatternImages(100, 100, PixelTypes)] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index a6d6d31f3..446c5e96a 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -26,7 +26,7 @@ namespace ImageSharp.Tests public static string[] ProgressiveTestJpegs = TestImages.Jpeg.Progressive.All; [Theory] - [WithFileCollection(nameof(BaselineTestJpegs), PixelTypes.Rgba32 | PixelTypes.StandardImageClass | PixelTypes.Argb32)] + [WithFileCollection(nameof(BaselineTestJpegs), PixelTypes.Rgba32 | PixelTypes.Rgba32 | PixelTypes.Argb32)] public void OpenBaselineJpeg_SaveBmp(TestImageProvider provider) where TPixel : struct, IPixel { @@ -37,7 +37,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32 | PixelTypes.StandardImageClass | PixelTypes.Argb32)] + [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32 | PixelTypes.Rgba32 | PixelTypes.Argb32)] public void OpenProgressiveJpeg_SaveBmp(TestImageProvider provider) where TPixel : struct, IPixel { @@ -48,11 +48,11 @@ namespace ImageSharp.Tests } [Theory] - [WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.StandardImageClass, JpegSubsample.Ratio420, 75)] - [WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.StandardImageClass, JpegSubsample.Ratio420, 100)] - [WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.StandardImageClass, JpegSubsample.Ratio444, 75)] - [WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.StandardImageClass, JpegSubsample.Ratio444, 100)] - [WithSolidFilledImages(8, 8, 255, 0, 0, PixelTypes.StandardImageClass, JpegSubsample.Ratio444, 100)] + [WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.Rgba32, JpegSubsample.Ratio420, 75)] + [WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.Rgba32, JpegSubsample.Ratio420, 100)] + [WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.Rgba32, JpegSubsample.Ratio444, 75)] + [WithSolidFilledImages(16, 16, 255, 0, 0, PixelTypes.Rgba32, JpegSubsample.Ratio444, 100)] + [WithSolidFilledImages(8, 8, 255, 0, 0, PixelTypes.Rgba32, JpegSubsample.Ratio444, 100)] public void DecodeGenerated_SaveBmp( TestImageProvider provider, JpegSubsample subsample, @@ -79,7 +79,7 @@ namespace ImageSharp.Tests } [Theory] - [WithSolidFilledImages(42, 88, 255, 0, 0, PixelTypes.StandardImageClass)] + [WithSolidFilledImages(42, 88, 255, 0, 0, PixelTypes.Rgba32)] public void DecodeGenerated_MetadataOnly( TestImageProvider provider) where TPixel : struct, IPixel diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index 1b4f3ea78..ab81c69b4 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -28,10 +28,10 @@ namespace ImageSharp.Tests } [Theory] - [WithFile(TestImages.Jpeg.Baseline.Snake, PixelTypes.StandardImageClass, 75, JpegSubsample.Ratio420)] - [WithFile(TestImages.Jpeg.Baseline.Lake, PixelTypes.StandardImageClass, 75, JpegSubsample.Ratio420)] - [WithFile(TestImages.Jpeg.Baseline.Snake, PixelTypes.StandardImageClass, 75, JpegSubsample.Ratio444)] - [WithFile(TestImages.Jpeg.Baseline.Lake, PixelTypes.StandardImageClass, 75, JpegSubsample.Ratio444)] + [WithFile(TestImages.Jpeg.Baseline.Snake, PixelTypes.Rgba32, 75, JpegSubsample.Ratio420)] + [WithFile(TestImages.Jpeg.Baseline.Lake, PixelTypes.Rgba32, 75, JpegSubsample.Ratio420)] + [WithFile(TestImages.Jpeg.Baseline.Snake, PixelTypes.Rgba32, 75, JpegSubsample.Ratio444)] + [WithFile(TestImages.Jpeg.Baseline.Lake, PixelTypes.Rgba32, 75, JpegSubsample.Ratio444)] public void LoadResizeSave(TestImageProvider provider, int quality, JpegSubsample subsample) where TPixel : struct, IPixel { @@ -49,8 +49,8 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32 | PixelTypes.StandardImageClass | PixelTypes.Argb32, JpegSubsample.Ratio420, 75)] - [WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32 | PixelTypes.StandardImageClass | PixelTypes.Argb32, JpegSubsample.Ratio444, 75)] + [WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32 | PixelTypes.Rgba32 | PixelTypes.Argb32, JpegSubsample.Ratio420, 75)] + [WithFileCollection(nameof(AllBmpFiles), PixelTypes.Rgba32 | PixelTypes.Rgba32 | PixelTypes.Argb32, JpegSubsample.Ratio444, 75)] public void OpenBmp_SaveJpeg(TestImageProvider provider, JpegSubsample subSample, int quality) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs index b41826e2f..aac3f4611 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs @@ -72,7 +72,7 @@ namespace ImageSharp.Tests Image[] testImages = testFiles.Select( - tf => TestImageProvider.File(tf, pixelTypeOverride: PixelTypes.StandardImageClass).GetImage()) + tf => TestImageProvider.File(tf, pixelTypeOverride: PixelTypes.Rgba32).GetImage()) .ToArray(); using (MemoryStream ms = new MemoryStream()) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegUtilsTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegUtilsTests.cs index f242faf12..f681e1d8f 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegUtilsTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegUtilsTests.cs @@ -40,7 +40,7 @@ namespace ImageSharp.Tests } [Theory] - [WithMemberFactory(nameof(CreateTestImage), PixelTypes.Rgba32| PixelTypes.StandardImageClass | PixelTypes.Argb32)] + [WithMemberFactory(nameof(CreateTestImage), PixelTypes.Rgba32| PixelTypes.Rgba32 | PixelTypes.Argb32)] public void CopyStretchedRGBTo_FromOrigo(TestImageProvider provider) where TPixel : struct, IPixel { @@ -62,7 +62,7 @@ namespace ImageSharp.Tests } [Theory] - [WithMemberFactory(nameof(CreateTestImage), PixelTypes.Rgba32| PixelTypes.StandardImageClass | PixelTypes.Argb32)] + [WithMemberFactory(nameof(CreateTestImage), PixelTypes.Rgba32| PixelTypes.Rgba32 | PixelTypes.Argb32)] public void CopyStretchedRGBTo_WithOffset(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 3d3f5b006..195a8dcb3 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -13,7 +13,7 @@ namespace ImageSharp.Tests public class PngDecoderTests { - private const PixelTypes PixelTypes = Tests.PixelTypes.StandardImageClass | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; + private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; public static readonly string[] TestFiles = { diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index 195eaba10..02edf7688 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -18,7 +18,7 @@ namespace ImageSharp.Tests public class PngEncoderTests : FileTestBase { - private const PixelTypes PixelTypes = Tests.PixelTypes.StandardImageClass | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; + private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; [Theory] [WithTestPatternImages(100, 100, PixelTypes, PngColorType.RgbWithAlpha)] diff --git a/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs index 22bb0b244..90f994f36 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs @@ -20,7 +20,7 @@ namespace ImageSharp.Tests.Formats.Png public class PngSmokeTests { [Theory] - [WithTestPatternImages(300, 300, PixelTypes.StandardImageClass)] + [WithTestPatternImages(300, 300, PixelTypes.Rgba32)] public void GeneralTest(TestImageProvider provider) where TPixel : struct, IPixel { @@ -41,7 +41,7 @@ namespace ImageSharp.Tests.Formats.Png } [Theory] - [WithTestPatternImages(100, 100, PixelTypes.StandardImageClass)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] public void CanSaveIndexedPng(TestImageProvider provider) where TPixel : struct, IPixel { @@ -105,7 +105,7 @@ namespace ImageSharp.Tests.Formats.Png //} [Theory] - [WithTestPatternImages(300, 300, PixelTypes.StandardImageClass)] + [WithTestPatternImages(300, 300, PixelTypes.Rgba32)] public void Resize(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs index f9a5a9628..e792de22f 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Binarization }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), DefaultPixelType)] public void ImageShouldApplyBinaryThresholdFilter(TestImageProvider provider, float value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Binarization } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BinaryThresholdValues), DefaultPixelType)] public void ImageShouldApplyBinaryThresholdInBox(TestImageProvider provider, float value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs index f5227e7d0..2948c1046 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/DitherTest.cs @@ -32,7 +32,7 @@ namespace ImageSharp.Tests.Processing.Binarization }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(Ditherers), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(Ditherers), DefaultPixelType)] public void ImageShouldApplyDitherFilter(TestImageProvider provider, string name, IOrderedDither ditherer) where TPixel : struct, IPixel { @@ -44,7 +44,7 @@ namespace ImageSharp.Tests.Processing.Binarization } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(Ditherers), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(Ditherers), DefaultPixelType)] public void ImageShouldApplyDitherFilterInBox(TestImageProvider provider, string name, IOrderedDither ditherer) where TPixel : struct, IPixel { @@ -61,7 +61,7 @@ namespace ImageSharp.Tests.Processing.Binarization } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(ErrorDiffusers), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ErrorDiffusers), DefaultPixelType)] public void ImageShouldApplyDiffusionFilter(TestImageProvider provider, string name, IErrorDiffuser diffuser) where TPixel : struct, IPixel { @@ -73,7 +73,7 @@ namespace ImageSharp.Tests.Processing.Binarization } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(ErrorDiffusers), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ErrorDiffusers), DefaultPixelType)] public void ImageShouldApplyDiffusionFilterInBox(TestImageProvider provider, string name, IErrorDiffuser diffuser) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs index 73847ae3a..d825b4993 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/BlackWhiteTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class BlackWhiteTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyBlackWhiteFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyBlackWhiteFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs index 6d144fdae..b56ec3471 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/ColorBlindnessTest.cs @@ -26,7 +26,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(ColorBlindnessFilters), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ColorBlindnessFilters), DefaultPixelType)] public void ImageShouldApplyColorBlindnessFilter(TestImageProvider provider, ColorBlindness colorBlindness) where TPixel : struct, IPixel { @@ -38,7 +38,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(ColorBlindnessFilters), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ColorBlindnessFilters), DefaultPixelType)] public void ImageShouldApplyColorBlindnessFilterInBox(TestImageProvider provider, ColorBlindness colorBlindness) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs index 11d53a4c7..89a388e4d 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/GrayscaleTest.cs @@ -23,7 +23,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix /// Use test patterns over loaded images to save decode time. /// [Theory] - [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, StandardPixelType)] + [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, DefaultPixelType)] public void ImageShouldApplyGrayscaleFilterAll(TestImageProvider provider, GrayscaleMode value) where TPixel : struct, IPixel { @@ -43,7 +43,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, StandardPixelType)] + [WithTestPatternImages(nameof(GrayscaleModeTypes), 50, 50, DefaultPixelType)] public void ImageShouldApplyGrayscaleFilterInBox(TestImageProvider provider, GrayscaleMode value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs index e7dffe74a..b71905374 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/HueTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(HueValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(HueValues), DefaultPixelType)] public void ImageShouldApplyHueFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(HueValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(HueValues), DefaultPixelType)] public void ImageShouldApplyHueFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs index 2da4e9fea..3a5d4f0d3 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/KodachromeTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class KodachromeTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyKodachromeFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyKodachromeFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs index 629d9793a..bfa37eef4 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/LomographTest.cs @@ -14,7 +14,7 @@ namespace ImageSharp.Tests public class LomographTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyLomographFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -26,7 +26,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyLomographFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs index b66589f4d..2bf1c3698 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/PolaroidTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class PolaroidTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyPolaroidFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyPolaroidFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs index 66c92262d..9212c09e8 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SaturationTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(SaturationValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(SaturationValues), DefaultPixelType)] public void ImageShouldApplySaturationFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(SaturationValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(SaturationValues), DefaultPixelType)] public void ImageShouldApplySaturationFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs index 5a54235fa..de536050b 100644 --- a/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs +++ b/tests/ImageSharp.Tests/Processing/ColorMatrix/SepiaTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix public class SepiaTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplySepiaFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.ColorMatrix } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplySepiaFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs index cbcdd6b49..b5ee876de 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/BoxBlurTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), DefaultPixelType)] public void ImageShouldApplyBoxBlurFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), DefaultPixelType)] public void ImageShouldApplyBoxBlurFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs index 880c5beae..220c0f466 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/DetectEdgesTest.cs @@ -28,7 +28,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(DetectEdgesFilters), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(DetectEdgesFilters), DefaultPixelType)] public void ImageShouldApplyDetectEdgesFilter(TestImageProvider provider, EdgeDetection detector) where TPixel : struct, IPixel { @@ -40,7 +40,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(DetectEdgesFilters), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(DetectEdgesFilters), DefaultPixelType)] public void ImageShouldApplyDetectEdgesFilterInBox(TestImageProvider provider, EdgeDetection detector) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs index 01b56dec8..dbaed9290 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianBlurTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)] public void ImageShouldApplyGaussianBlurFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)] public void ImageShouldApplyGaussianBlurFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs index f0ac37e1b..44296d975 100644 --- a/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs +++ b/tests/ImageSharp.Tests/Processing/Convolution/GaussianSharpenTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Convolution }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), DefaultPixelType)] public void ImageShouldApplyGaussianSharpenFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Convolution } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), DefaultPixelType)] public void ImageShouldApplyGaussianSharpenFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs b/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs index 737076270..63366dc1d 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/AlphaTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Effects }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(AlphaValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(AlphaValues), DefaultPixelType)] public void ImageShouldApplyAlphaFilter(TestImageProvider provider, float value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Effects } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(AlphaValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(AlphaValues), DefaultPixelType)] public void ImageShouldApplyAlphaFilterInBox(TestImageProvider provider, float value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs b/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs index 97e6471f8..c3fda4cd4 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/BackgroundColorTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.Effects public class BackgroundColorTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyBackgroundColorFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.Effects } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyBackgroundColorFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs b/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs index 580b18187..4c0217fed 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/BrightnessTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Effects }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BrightnessValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BrightnessValues), DefaultPixelType)] public void ImageShouldApplyBrightnessFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Effects } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(BrightnessValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(BrightnessValues), DefaultPixelType)] public void ImageShouldApplyBrightnessFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs b/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs index 3003e9ddc..ac217e9f6 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/ContrastTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Effects }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(ContrastValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ContrastValues), DefaultPixelType)] public void ImageShouldApplyContrastFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests.Processing.Effects } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(ContrastValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(ContrastValues), DefaultPixelType)] public void ImageShouldApplyContrastFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs b/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs index 8ad36e54c..80e345092 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/InvertTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.Effects public class InvertTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyInvertFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.Effects } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyInvertFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs b/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs index de9bf583d..7d02ace3d 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/OilPaintTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), DefaultPixelType)] public void ImageShouldApplyOilPaintFilter(TestImageProvider provider, int levels, int brushSize) where TPixel : struct, IPixel { @@ -31,7 +31,7 @@ namespace ImageSharp.Tests } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), DefaultPixelType)] public void ImageShouldApplyOilPaintFilterInBox(TestImageProvider provider, int levels, int brushSize) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs b/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs index d7cff18c3..740b78c55 100644 --- a/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs +++ b/tests/ImageSharp.Tests/Processing/Effects/PixelateTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Effects }; [Theory] - [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.StandardImageClass)] + [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.Rgba32)] public void ImageShouldApplyPixelateFilter(TestImageProvider provider, int value) where TPixel : struct, IPixel { @@ -47,7 +47,7 @@ namespace ImageSharp.Tests.Processing.Effects } [Theory] - [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.StandardImageClass)] + [WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.Rgba32)] public void ImageShouldApplyPixelateFilterInBox(TestImageProvider provider, int value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs b/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs index 0c4ad72ee..a233e204c 100644 --- a/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs +++ b/tests/ImageSharp.Tests/Processing/Overlays/GlowTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.Overlays public class GlowTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyGlowFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.Overlays } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyGlowFilterColor(TestImageProvider provider) where TPixel : struct, IPixel { @@ -36,7 +36,7 @@ namespace ImageSharp.Tests.Processing.Overlays } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyGlowFilterRadius(TestImageProvider provider) where TPixel : struct, IPixel { @@ -48,7 +48,7 @@ namespace ImageSharp.Tests.Processing.Overlays } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyGlowFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs b/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs index 583331bad..85ccfca6f 100644 --- a/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs +++ b/tests/ImageSharp.Tests/Processing/Overlays/VignetteTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.Overlays public class VignetteTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyVignetteFilter(TestImageProvider provider) where TPixel : struct, IPixel { @@ -24,7 +24,7 @@ namespace ImageSharp.Tests.Processing.Overlays } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyVignetteFilterColor(TestImageProvider provider) where TPixel : struct, IPixel { @@ -36,7 +36,7 @@ namespace ImageSharp.Tests.Processing.Overlays } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyVignetteFilterRadius(TestImageProvider provider) where TPixel : struct, IPixel { @@ -48,7 +48,7 @@ namespace ImageSharp.Tests.Processing.Overlays } [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldApplyVignetteFilterInBox(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs index d77a54c4f..7bc0c8bb5 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs @@ -29,7 +29,7 @@ namespace ImageSharp.Tests.Processing.Transforms }; [Theory] - [WithFileCollection(nameof(FlipFiles), nameof(OrientationValues), StandardPixelType)] + [WithFileCollection(nameof(FlipFiles), nameof(OrientationValues), DefaultPixelType)] public void ImageShouldAutoRotate(TestImageProvider provider, RotateType rotateType, FlipType flipType, ushort orientation) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs index 82ae2e8b8..ca20abf79 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/CropTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.Transforms public class CropTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldCrop(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs index 5b1dd0442..24febd5b2 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/EntropyCropTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Transforms }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(EntropyCropValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(EntropyCropValues), DefaultPixelType)] public void ImageShouldEntropyCrop(TestImageProvider provider, float value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs index e002ebc70..45ab1e5f8 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/FlipTests.cs @@ -23,7 +23,7 @@ namespace ImageSharp.Tests.Processing.Transforms }; [Theory] - [WithFileCollection(nameof(FlipFiles), nameof(FlipValues), StandardPixelType)] + [WithFileCollection(nameof(FlipFiles), nameof(FlipValues), DefaultPixelType)] public void ImageShouldFlip(TestImageProvider provider, FlipType flipType) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs index ee03193ae..666f3df78 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs @@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Processing.Transforms public class PadTest : FileTestBase { [Theory] - [WithFileCollection(nameof(DefaultFiles), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] public void ImageShouldPad(TestImageProvider provider) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs index 8244f17c3..008d041e7 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs @@ -33,7 +33,7 @@ namespace ImageSharp.Tests.Processing.Transforms }; [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResize(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -45,7 +45,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeFromSourceRectangle(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -60,7 +60,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeWidthAndKeepAspect(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -72,7 +72,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeHeightAndKeepAspect(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -84,7 +84,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeWithCropWidthMode(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -102,7 +102,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeWithCropHeightMode(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -120,7 +120,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeWithPadMode(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -139,7 +139,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeWithBoxPadMode(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -158,7 +158,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeWithMaxMode(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -177,7 +177,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeWithMinMode(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { @@ -196,7 +196,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), StandardPixelType)] + [WithFileCollection(nameof(ResizeFiles), nameof(ReSamplers), DefaultPixelType)] public void ImageShouldResizeWithStretchMode(TestImageProvider provider, string name, IResampler sampler) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs index bdea4b223..f85ef6f13 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs @@ -25,7 +25,7 @@ namespace ImageSharp.Tests.Processing.Transforms }; [Theory] - [WithFileCollection(nameof(FlipFiles), nameof(RotateFlipValues), StandardPixelType)] + [WithFileCollection(nameof(FlipFiles), nameof(RotateFlipValues), DefaultPixelType)] public void ImageShouldRotateFlip(TestImageProvider provider, RotateType rotateType, FlipType flipType) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs index 42e89bb5f..1f1856429 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs @@ -29,7 +29,7 @@ namespace ImageSharp.Tests.Processing.Transforms }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(RotateFloatValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(RotateFloatValues), DefaultPixelType)] public void ImageShouldRotate(TestImageProvider provider, float value) where TPixel : struct, IPixel { @@ -41,7 +41,7 @@ namespace ImageSharp.Tests.Processing.Transforms } [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(RotateEnumValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(RotateEnumValues), DefaultPixelType)] public void ImageShouldRotateEnum(TestImageProvider provider, RotateType value) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs index 2c393acac..f2c2d7cbd 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs @@ -19,7 +19,7 @@ namespace ImageSharp.Tests.Processing.Transforms }; [Theory] - [WithFileCollection(nameof(DefaultFiles), nameof(SkewValues), StandardPixelType)] + [WithFileCollection(nameof(DefaultFiles), nameof(SkewValues), DefaultPixelType)] public void ImageShouldSkew(TestImageProvider provider, float x, float y) where TPixel : struct, IPixel { diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs index 9e8e0dce3..16eecd2fc 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs @@ -18,7 +18,7 @@ namespace ImageSharp.Tests private class FileProvider : TestImageProvider, IXunitSerializable { // Need PixelTypes in the dictionary key, because result images of TestImageProvider.FileProvider - // are shared between PixelTypes.Color & PixelTypes.StandardImageClass + // are shared between PixelTypes.Color & PixelTypes.Rgba32 private class Key : Tuple { public Key(PixelTypes item1, string item2) diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs index bf30d4847..03a685d34 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageProviders/TestImageProvider.cs @@ -107,12 +107,12 @@ namespace ImageSharp.Tests this.TypeName = typeName; this.MethodName = methodName; - if (pixelTypeOverride == PixelTypes.StandardImageClass) + if (pixelTypeOverride == PixelTypes.Rgba32) { this.Factory = new ImageFactory() as GenericFactory; } - this.Utility = new ImagingTestCaseUtility() + this.Utility = new ImagingTestCaseUtility { SourceFileOrDescription = this.SourceFileOrDescription, PixelTypeName = this.PixelType.ToString() diff --git a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs index f64b77271..5c676d07c 100644 --- a/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs +++ b/tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs @@ -52,11 +52,6 @@ namespace ImageSharp.Tests Short4 = 1 << 17, - /// - /// Triggers instantiating the subclass of - /// - StandardImageClass = 1 << 29, - // TODO: Add multi-flag entries by rules defined in PackedPixelConverterHelper // "All" is handled as a separate, individual case instead of using bitwise OR diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs index 115fb895d..e42cbe193 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtilityExtensions.cs @@ -38,14 +38,13 @@ namespace ImageSharp.Tests // Add PixelFormat types string nameSpace = typeof(Alpha8).FullName; nameSpace = nameSpace.Substring(0, nameSpace.Length - typeof(Alpha8).Name.Length - 1); - foreach (PixelTypes pt in AllConcretePixelTypes.Where(pt => pt != PixelTypes.StandardImageClass && pt != PixelTypes.Rgba32)) + foreach (PixelTypes pt in AllConcretePixelTypes.Where(pt => pt != PixelTypes.Rgba32)) { string typeName = $"{nameSpace}.{pt}"; Type t = ImageSharpAssembly.GetType(typeName); PixelTypes2ClrTypes[pt] = t ?? throw new InvalidOperationException($"Could not find: {typeName}"); ClrTypes2PixelTypes[t] = pt; } - PixelTypes2ClrTypes[PixelTypes.StandardImageClass] = defaultPixelFormatType; } public static bool HasFlag(this PixelTypes pixelTypes, PixelTypes flag) => (pixelTypes & flag) == flag; diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs index 4d3a0d991..6bd5b392d 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs @@ -50,7 +50,7 @@ namespace ImageSharp.Tests [Theory] [WithBlankImages(1, 1, PixelTypes.Rgba32, PixelTypes.Rgba32)] [WithBlankImages(1, 1, PixelTypes.Alpha8, PixelTypes.Alpha8)] - [WithBlankImages(1, 1, PixelTypes.StandardImageClass, PixelTypes.StandardImageClass)] + [WithBlankImages(1, 1, PixelTypes.Rgba32, PixelTypes.Rgba32)] public void PixelType_PropertyValueIsCorrect(TestImageProvider provider, PixelTypes expected) where TPixel : struct, IPixel { @@ -58,8 +58,8 @@ namespace ImageSharp.Tests } [Theory] - [WithBlankImages(1, 1, PixelTypes.StandardImageClass)] - [WithFile(TestImages.Bmp.F, PixelTypes.StandardImageClass)] + [WithBlankImages(1, 1, PixelTypes.Rgba32)] + [WithFile(TestImages.Bmp.F, PixelTypes.Rgba32)] public void PixelTypes_ColorWithDefaultImageClass_TriggersCreatingTheNonGenericDerivedImageClass( TestImageProvider provider) where TPixel : struct, IPixel @@ -144,7 +144,7 @@ namespace ImageSharp.Tests { Image img = provider.GetImage(); Assert.Equal(img.Width, 3); - if (provider.PixelType == PixelTypes.StandardImageClass) + if (provider.PixelType == PixelTypes.Rgba32) { Assert.IsType>(img); } diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs index 9ff0ca64e..5195f2062 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs @@ -89,7 +89,7 @@ namespace ImageSharp.Tests [InlineData(PixelTypes.Rgba32, typeof(Rgba32))] [InlineData(PixelTypes.Argb32, typeof(Argb32))] [InlineData(PixelTypes.HalfVector4, typeof(HalfVector4))] - [InlineData(PixelTypes.StandardImageClass, typeof(Rgba32))] + [InlineData(PixelTypes.Rgba32, typeof(Rgba32))] public void ToType(PixelTypes pt, Type expectedType) { Assert.Equal(pt.ToType(), expectedType); @@ -114,7 +114,7 @@ namespace ImageSharp.Tests [Fact] public void ToTypes() { - PixelTypes pixelTypes = PixelTypes.Alpha8 | PixelTypes.Bgr565 | PixelTypes.Rgba32 | PixelTypes.HalfVector2 | PixelTypes.StandardImageClass; + PixelTypes pixelTypes = PixelTypes.Alpha8 | PixelTypes.Bgr565 | PixelTypes.Rgba32 | PixelTypes.HalfVector2 | PixelTypes.Rgba32; IEnumerable> expanded = pixelTypes.ExpandAllTypes(); @@ -124,7 +124,7 @@ namespace ImageSharp.Tests AssertContainsPixelType(PixelTypes.Bgr565, expanded); AssertContainsPixelType(PixelTypes.Rgba32, expanded); AssertContainsPixelType(PixelTypes.HalfVector2, expanded); - AssertContainsPixelType(PixelTypes.StandardImageClass, expanded); + AssertContainsPixelType(PixelTypes.Rgba32, expanded); } [Fact] @@ -134,7 +134,7 @@ namespace ImageSharp.Tests Assert.True(expanded.Length >= TestUtilityExtensions.GetAllPixelTypes().Length - 2); AssertContainsPixelType(PixelTypes.Rgba32, expanded); - AssertContainsPixelType(PixelTypes.StandardImageClass, expanded); + AssertContainsPixelType(PixelTypes.Rgba32, expanded); } } } From d821f201e9573c7137d8b6d084b816261fdde163 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 31 May 2017 10:03:23 +1000 Subject: [PATCH 73/84] Fix broken test --- .../TestUtilities/Tests/TestUtilityExtensionsTests.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs index 5195f2062..a35c73aef 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs @@ -114,15 +114,14 @@ namespace ImageSharp.Tests [Fact] public void ToTypes() { - PixelTypes pixelTypes = PixelTypes.Alpha8 | PixelTypes.Bgr565 | PixelTypes.Rgba32 | PixelTypes.HalfVector2 | PixelTypes.Rgba32; + PixelTypes pixelTypes = PixelTypes.Alpha8 | PixelTypes.Bgr565 | PixelTypes.HalfVector2 | PixelTypes.Rgba32; IEnumerable> expanded = pixelTypes.ExpandAllTypes(); - Assert.Equal(expanded.Count(), 5); + Assert.Equal(expanded.Count(), 4); AssertContainsPixelType(PixelTypes.Alpha8, expanded); AssertContainsPixelType(PixelTypes.Bgr565, expanded); - AssertContainsPixelType(PixelTypes.Rgba32, expanded); AssertContainsPixelType(PixelTypes.HalfVector2, expanded); AssertContainsPixelType(PixelTypes.Rgba32, expanded); } From b6c8cb2e3d6eb205df412924bd48b1e83b1a3e81 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 31 May 2017 13:47:38 +1000 Subject: [PATCH 74/84] Fix #233 --- .../Transforms/Options/ResizeHelper.cs | 77 ++++++++++--------- .../Processing/Transforms/Resize.cs | 8 +- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs b/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs index d9b9b5556..712efec12 100644 --- a/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs +++ b/src/ImageSharp/Processing/Transforms/Options/ResizeHelper.cs @@ -5,7 +5,6 @@ namespace ImageSharp.Processing { - using System; using System.Linq; using ImageSharp.PixelFormats; @@ -86,17 +85,17 @@ namespace ImageSharp.Processing if (options.CenterCoordinates.Any()) { - float center = -(ratio * sourceHeight) * options.CenterCoordinates.First(); - destinationY = (int)center + (height / 2); + float center = -(ratio * sourceHeight) * options.CenterCoordinates.ToArray()[1]; + destinationY = (int)MathF.Round(center + (height / 2F)); if (destinationY > 0) { destinationY = 0; } - if (destinationY < (int)(height - (sourceHeight * ratio))) + if (destinationY < (int)MathF.Round(height - (sourceHeight * ratio))) { - destinationY = (int)(height - (sourceHeight * ratio)); + destinationY = (int)MathF.Round(height - (sourceHeight * ratio)); } } else @@ -111,10 +110,10 @@ namespace ImageSharp.Processing case AnchorPosition.Bottom: case AnchorPosition.BottomLeft: case AnchorPosition.BottomRight: - destinationY = (int)(height - (sourceHeight * ratio)); + destinationY = (int)MathF.Round(height - (sourceHeight * ratio)); break; default: - destinationY = (int)((height - (sourceHeight * ratio)) / 2); + destinationY = (int)MathF.Round((height - (sourceHeight * ratio)) / 2F); break; } } @@ -127,17 +126,17 @@ namespace ImageSharp.Processing if (options.CenterCoordinates.Any()) { - float center = -(ratio * sourceWidth) * options.CenterCoordinates.ToArray()[1]; - destinationX = (int)center + (width / 2); + float center = -(ratio * sourceWidth) * options.CenterCoordinates.First(); + destinationX = (int)MathF.Round(center + (width / 2F)); if (destinationX > 0) { destinationX = 0; } - if (destinationX < (int)(width - (sourceWidth * ratio))) + if (destinationX < (int)MathF.Round(width - (sourceWidth * ratio))) { - destinationX = (int)(width - (sourceWidth * ratio)); + destinationX = (int)MathF.Round(width - (sourceWidth * ratio)); } } else @@ -152,10 +151,10 @@ namespace ImageSharp.Processing case AnchorPosition.Right: case AnchorPosition.TopRight: case AnchorPosition.BottomRight: - destinationX = (int)(width - (sourceWidth * ratio)); + destinationX = (int)MathF.Round(width - (sourceWidth * ratio)); break; default: - destinationX = (int)((width - (sourceWidth * ratio)) / 2); + destinationX = (int)MathF.Round((width - (sourceWidth * ratio)) / 2F); break; } } @@ -202,7 +201,7 @@ namespace ImageSharp.Processing if (percentHeight < percentWidth) { ratio = percentHeight; - destinationWidth = Convert.ToInt32(sourceWidth * percentHeight); + destinationWidth = (int)MathF.Round(sourceWidth * percentHeight); switch (options.Position) { @@ -214,17 +213,17 @@ namespace ImageSharp.Processing case AnchorPosition.Right: case AnchorPosition.TopRight: case AnchorPosition.BottomRight: - destinationX = (int)(width - (sourceWidth * ratio)); + destinationX = (int)MathF.Round(width - (sourceWidth * ratio)); break; default: - destinationX = Convert.ToInt32((width - (sourceWidth * ratio)) / 2); + destinationX = (int)MathF.Round((width - (sourceWidth * ratio)) / 2F); break; } } else { ratio = percentWidth; - destinationHeight = Convert.ToInt32(sourceHeight * percentWidth); + destinationHeight = (int)MathF.Round(sourceHeight * percentWidth); switch (options.Position) { @@ -236,10 +235,10 @@ namespace ImageSharp.Processing case AnchorPosition.Bottom: case AnchorPosition.BottomLeft: case AnchorPosition.BottomRight: - destinationY = (int)(height - (sourceHeight * ratio)); + destinationY = (int)MathF.Round(height - (sourceHeight * ratio)); break; default: - destinationY = (int)((height - (sourceHeight * ratio)) / 2); + destinationY = (int)MathF.Round((height - (sourceHeight * ratio)) / 2F); break; } } @@ -274,8 +273,8 @@ namespace ImageSharp.Processing float percentHeight = MathF.Abs(height / (float)sourceHeight); float percentWidth = MathF.Abs(width / (float)sourceWidth); - int boxPadHeight = height > 0 ? height : Convert.ToInt32(sourceHeight * percentWidth); - int boxPadWidth = width > 0 ? width : Convert.ToInt32(sourceWidth * percentHeight); + int boxPadHeight = height > 0 ? height : (int)MathF.Round(sourceHeight * percentWidth); + int boxPadWidth = width > 0 ? width : (int)MathF.Round(sourceWidth * percentHeight); // Only calculate if upscaling. if (sourceWidth < boxPadWidth && sourceHeight < boxPadHeight) @@ -356,17 +355,17 @@ namespace ImageSharp.Processing float percentWidth = MathF.Abs(width / (float)source.Width); // Integers must be cast to floats to get needed precision - float ratio = (float)options.Size.Height / options.Size.Width; - float sourceRatio = (float)source.Height / source.Width; + float ratio = options.Size.Height / (float)options.Size.Width; + float sourceRatio = source.Height / (float)source.Width; if (sourceRatio < ratio) { - destinationHeight = Convert.ToInt32(source.Height * percentWidth); + destinationHeight = (int)MathF.Round(source.Height * percentWidth); height = destinationHeight; } else { - destinationWidth = Convert.ToInt32(source.Width * percentHeight); + destinationWidth = (int)MathF.Round(source.Width * percentHeight); width = destinationWidth; } @@ -389,35 +388,37 @@ namespace ImageSharp.Processing { int width = options.Size.Width; int height = options.Size.Height; + int sourceWidth = source.Width; + int sourceHeight = source.Height; int destinationWidth; int destinationHeight; // Don't upscale - if (width > source.Width || height > source.Height) + if (width > sourceWidth || height > sourceHeight) { - options.Size = new Size(source.Width, source.Height); - return new Rectangle(0, 0, source.Width, source.Height); + options.Size = new Size(sourceWidth, sourceHeight); + return new Rectangle(0, 0, sourceWidth, sourceHeight); } // Fractional variants for preserving aspect ratio. - float percentHeight = MathF.Abs(height / (float)source.Height); - float percentWidth = MathF.Abs(width / (float)source.Width); + float percentHeight = MathF.Abs(height / (float)sourceHeight); + float percentWidth = MathF.Abs(width / (float)sourceWidth); - float sourceRatio = (float)source.Height / source.Width; + float sourceRatio = (float)sourceHeight / sourceWidth; // Find the shortest distance to go. - int widthDiff = source.Width - width; - int heightDiff = source.Height - height; + int widthDiff = sourceWidth - width; + int heightDiff = sourceHeight - height; if (widthDiff < heightDiff) { - destinationHeight = Convert.ToInt32(width * sourceRatio); + destinationHeight = (int)MathF.Round(width * sourceRatio); height = destinationHeight; destinationWidth = width; } else if (widthDiff > heightDiff) { - destinationWidth = Convert.ToInt32(height / sourceRatio); + destinationWidth = (int)MathF.Round(height / sourceRatio); destinationHeight = height; width = destinationWidth; } @@ -426,13 +427,13 @@ namespace ImageSharp.Processing if (height > width) { destinationWidth = width; - destinationHeight = Convert.ToInt32(source.Height * percentWidth); + destinationHeight = (int)MathF.Round(sourceHeight * percentWidth); height = destinationHeight; } else { destinationHeight = height; - destinationWidth = Convert.ToInt32(source.Width * percentHeight); + destinationWidth = (int)MathF.Round(sourceWidth * percentHeight); width = destinationWidth; } } @@ -442,4 +443,4 @@ namespace ImageSharp.Processing return new Rectangle(0, 0, destinationWidth, destinationHeight); } } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Transforms/Resize.cs b/src/ImageSharp/Processing/Transforms/Resize.cs index 271a111ca..3399ff0e3 100644 --- a/src/ImageSharp/Processing/Transforms/Resize.cs +++ b/src/ImageSharp/Processing/Transforms/Resize.cs @@ -29,12 +29,12 @@ namespace ImageSharp // Ensure size is populated across both dimensions. if (options.Size.Width == 0 && options.Size.Height > 0) { - options.Size = new Size(source.Width * options.Size.Height / source.Height, options.Size.Height); + options.Size = new Size((int)MathF.Round(source.Width * options.Size.Height / (float)source.Height), options.Size.Height); } if (options.Size.Height == 0 && options.Size.Width > 0) { - options.Size = new Size(options.Size.Width, source.Height * options.Size.Width / source.Width); + options.Size = new Size(options.Size.Width, (int)MathF.Round(source.Height * options.Size.Width / (float)source.Width)); } Rectangle targetRectangle = ResizeHelper.CalculateTargetLocationAndBounds(source, options); @@ -158,13 +158,13 @@ namespace ImageSharp { if (width == 0 && height > 0) { - width = source.Width * height / source.Height; + width = (int)MathF.Round(source.Width * height / (float)source.Height); targetRectangle.Width = width; } if (height == 0 && width > 0) { - height = source.Height * width / source.Width; + height = (int)MathF.Round(source.Height * width / (float)source.Width); targetRectangle.Height = height; } From dbd9f70cc8f803ba84e28448e9819031e9a3758d Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Wed, 31 May 2017 06:23:54 +0100 Subject: [PATCH 75/84] switch constructor and field back to array --- src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs index 65ec9eabf..37cfff9e9 100644 --- a/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs +++ b/src/ImageSharp.Drawing/Pens/Pen{TPixel}.cs @@ -27,8 +27,8 @@ namespace ImageSharp.Drawing.Pens public class Pen : IPen where TPixel : struct, IPixel { - private static readonly ReadOnlySpan EmptyPattern = new float[0]; - private readonly ReadOnlySpan pattern; + private static readonly float[] EmptyPattern = new float[0]; + private readonly float[] pattern; /// /// Initializes a new instance of the class. @@ -36,7 +36,7 @@ namespace ImageSharp.Drawing.Pens /// The color. /// The width. /// The pattern. - public Pen(TPixel color, float width, ReadOnlySpan pattern) + public Pen(TPixel color, float width, float[] pattern) : this(new SolidBrush(color), width, pattern) { } @@ -47,7 +47,7 @@ namespace ImageSharp.Drawing.Pens /// The brush. /// The width. /// The pattern. - public Pen(IBrush brush, float width, ReadOnlySpan pattern) + public Pen(IBrush brush, float width, float[] pattern) { this.StrokeFill = brush; this.StrokeWidth = width; From 8e6aecbd0b31309d75a6de5410756b345eb3293a Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Wed, 31 May 2017 19:30:09 +0100 Subject: [PATCH 76/84] add unit tests --- .../Drawing/Paths/DrawPathCollection.cs | 179 ++++++++++++++++++ .../Drawing/Paths/FillPathCollection.cs | 131 +++++++++++++ 2 files changed, 310 insertions(+) create mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs create mode 100644 tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs new file mode 100644 index 000000000..5148236d8 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs @@ -0,0 +1,179 @@ + +namespace ImageSharp.Tests.Drawing.Paths +{ + using System; + + using ImageSharp.Drawing.Brushes; + + using Xunit; + using ImageSharp.Drawing; + using System.Numerics; + using SixLabors.Shapes; + using ImageSharp.Drawing.Processors; + using ImageSharp.Drawing.Pens; + using ImageSharp.PixelFormats; + + public class DrawPathCollection : IDisposable + { + float thickness = 7.2f; + GraphicsOptions noneDefault = new GraphicsOptions(); + Rgba32 color = Rgba32.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + Pen pen = new Pen(Rgba32.Gray, 99.9f); + IPath path1 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { + new Vector2(10,10), + new Vector2(20,10), + new Vector2(20,10), + new Vector2(30,10), + })); + + IPath path2 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { + new Vector2(10,10), + new Vector2(20,10), + new Vector2(20,10), + new Vector2(30,10), + })); + + IPathCollection pathCollection; + private ProcessorWatchingImage img; + + public DrawPathCollection() + { + this.pathCollection = new PathCollection(this.path1, this.path2); + this.img = new Paths.ProcessorWatchingImage(10, 10); + } + + public void Dispose() + { + img.Dispose(); + } + + [Fact] + public void CorrectlySetsBrushThicknessAndPath() + { + img.Draw(brush, thickness, pathCollection); + + Assert.NotEmpty(img.ProcessorApplications); + + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, this.pathCollection); + + Pen pen = Assert.IsType>(processor.Pen); + Assert.Equal(brush, pen.Brush); + Assert.Equal(thickness, pen.Width); + } + } + + [Fact] + public void CorrectlySetsBrushThicknessPathAndOptions() + { + img.Draw(brush, thickness, pathCollection, noneDefault); + + Assert.NotEmpty(img.ProcessorApplications); + + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Pen pen = Assert.IsType>(processor.Pen); + Assert.Equal(brush, pen.Brush); + Assert.Equal(thickness, pen.Width); + } + } + + [Fact] + public void CorrectlySetsColorThicknessAndPath() + { + img.Draw(color, thickness, pathCollection); + + Assert.NotEmpty(img.ProcessorApplications); + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Pen pen = Assert.IsType>(processor.Pen); + Assert.Equal(thickness, pen.Width); + + SolidBrush brush = Assert.IsType>(pen.Brush); + Assert.Equal(color, brush.Color); + } + } + + [Fact] + public void CorrectlySetsColorThicknessPathAndOptions() + { + img.Draw(color, thickness, pathCollection, noneDefault); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Pen pen = Assert.IsType>(processor.Pen); + Assert.Equal(thickness, pen.Width); + + SolidBrush brush = Assert.IsType>(pen.Brush); + Assert.Equal(color, brush.Color); + } + } + + [Fact] + public void CorrectlySetsPenAndPath() + { + img.Draw(pen, pathCollection); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Assert.Equal(pen, processor.Pen); + } + } + + [Fact] + public void CorrectlySetsPenPathAndOptions() + { + img.Draw(pen, pathCollection, noneDefault); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapePath shapepath = Assert.IsType(processor.Path); + Assert.Contains(shapepath.Path, pathCollection); + + Assert.Equal(pen, processor.Pen); + } + } + } +} diff --git a/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs new file mode 100644 index 000000000..e60ac0c13 --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/Paths/FillPathCollection.cs @@ -0,0 +1,131 @@ + +namespace ImageSharp.Tests.Drawing.Paths +{ + using System; + using ImageSharp; + using ImageSharp.Drawing.Brushes; + using Xunit; + using ImageSharp.Drawing; + using System.Numerics; + using SixLabors.Shapes; + using ImageSharp.Drawing.Processors; + using ImageSharp.PixelFormats; + + public class FillPathCollection : IDisposable + { + GraphicsOptions noneDefault = new GraphicsOptions(); + Rgba32 color = Rgba32.HotPink; + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + IPath path1 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { + new Vector2(10,10), + new Vector2(20,10), + new Vector2(20,10), + new Vector2(30,10), + })); + IPath path2 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { + new Vector2(10,10), + new Vector2(20,10), + new Vector2(20,10), + new Vector2(30,10), + })); + + IPathCollection pathCollection; + + private ProcessorWatchingImage img; + + public FillPathCollection() + { + this.pathCollection = new PathCollection(path1, path2); + this.img = new ProcessorWatchingImage(10, 10); + } + + public void Dispose() + { + img.Dispose(); + } + + [Fact] + public void CorrectlySetsBrushAndPath() + { + img.Fill(brush, pathCollection); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + FillRegionProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapeRegion region = Assert.IsType(processor.Region); + + // path is converted to a polygon before filling + Polygon polygon = Assert.IsType(region.Shape); + LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); + + Assert.Equal(brush, processor.Brush); + } + } + + [Fact] + public void CorrectlySetsBrushPathOptions() + { + img.Fill(brush, pathCollection, noneDefault); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + FillRegionProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapeRegion region = Assert.IsType(processor.Region); + Polygon polygon = Assert.IsType(region.Shape); + LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); + + Assert.Equal(brush, processor.Brush); + } + } + + [Fact] + public void CorrectlySetsColorAndPath() + { + img.Fill(color, pathCollection); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + FillRegionProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(GraphicsOptions.Default, processor.Options); + + ShapeRegion region = Assert.IsType(processor.Region); + Polygon polygon = Assert.IsType(region.Shape); + LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); + + SolidBrush brush = Assert.IsType>(processor.Brush); + Assert.Equal(color, brush.Color); + } + } + + [Fact] + public void CorrectlySetsColorPathAndOptions() + { + img.Fill(color, pathCollection, noneDefault); + + Assert.Equal(2, img.ProcessorApplications.Count); + for (var i = 0; i < 2; i++) + { + FillRegionProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); + + Assert.Equal(noneDefault, processor.Options); + + ShapeRegion region = Assert.IsType(processor.Region); + Polygon polygon = Assert.IsType(region.Shape); + LinearLineSegment segments = Assert.IsType(polygon.LineSegments[0]); + + SolidBrush brush = Assert.IsType>(processor.Brush); + Assert.Equal(color, brush.Color); + } + } + } +} From 7c81b0cc356297c8dfcad436af3830f9eeab7ad9 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Wed, 31 May 2017 20:45:29 +0100 Subject: [PATCH 77/84] add draw text along path extension methods --- .../ImageSharp.Drawing.csproj | 2 +- .../Paths/DrawPathCollection.cs | 2 +- src/ImageSharp.Drawing/Text/DrawText.Path.cs | 200 ++++++++++++++ src/ImageSharp.Drawing/Text/DrawText.cs | 2 +- .../Drawing/Paths/DrawPathCollection.cs | 179 ------------- .../Drawing/Text/DrawText.Path.cs | 251 ++++++++++++++++++ 6 files changed, 454 insertions(+), 182 deletions(-) create mode 100644 src/ImageSharp.Drawing/Text/DrawText.Path.cs delete mode 100644 tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs create mode 100644 tests/ImageSharp.Tests/Drawing/Text/DrawText.Path.cs diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index a9afe37f8..9d24c1777 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -36,7 +36,7 @@ - + All diff --git a/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs b/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs index 5cb499415..877737653 100644 --- a/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs +++ b/src/ImageSharp.Drawing/Paths/DrawPathCollection.cs @@ -30,7 +30,7 @@ namespace ImageSharp { foreach (IPath path in paths) { - source.Draw(pen, new ShapePath(path), options); + source.Draw(pen, path, options); } return source; diff --git a/src/ImageSharp.Drawing/Text/DrawText.Path.cs b/src/ImageSharp.Drawing/Text/DrawText.Path.cs new file mode 100644 index 000000000..2bc23b64b --- /dev/null +++ b/src/ImageSharp.Drawing/Text/DrawText.Path.cs @@ -0,0 +1,200 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System.Numerics; + + using Drawing; + using Drawing.Brushes; + using Drawing.Pens; + using ImageSharp.PixelFormats; + using SixLabors.Fonts; + using SixLabors.Shapes; + + /// + /// Extension methods for the type. + /// + public static partial class ImageExtensions + { + /// + /// Draws the text onto the the image filled via the brush. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The color. + /// The path. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, TPixel color, IPath path) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, color, path, TextGraphicsOptions.Default); + } + + /// + /// Draws the text onto the the image filled via the brush. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The color. + /// The path. + /// The options. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, TPixel color, IPath path, TextGraphicsOptions options) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, Brushes.Solid(color), null, path, options); + } + + /// + /// Draws the text onto the the image filled via the brush. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The brush. + /// The location. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPath path) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, brush, path, TextGraphicsOptions.Default); + } + + /// + /// Draws the text onto the the image filled via the brush. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The brush. + /// The path. + /// The options. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPath path, TextGraphicsOptions options) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, brush, null, path, options); + } + + /// + /// Draws the text onto the the image outlined via the pen. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The pen. + /// The path. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IPen pen, IPath path) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, pen, path, TextGraphicsOptions.Default); + } + + /// + /// Draws the text onto the the image outlined via the pen. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The pen. + /// The path. + /// The options. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IPen pen, IPath path, TextGraphicsOptions options) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, null, pen, path, options); + } + + /// + /// Draws the text onto the the image filled via the brush then outlined via the pen. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The brush. + /// The pen. + /// The path. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPen pen, IPath path) + where TPixel : struct, IPixel + { + return source.DrawText(text, font, brush, pen, path, TextGraphicsOptions.Default); + } + + /// + /// Draws the text onto the the image filled via the brush then outlined via the pen. + /// + /// The type of the color. + /// The image this method extends. + /// The text. + /// The font. + /// The brush. + /// The pen. + /// The path. + /// The options. + /// + /// The . + /// + public static Image DrawText(this Image source, string text, Font font, IBrush brush, IPen pen, IPath path, TextGraphicsOptions options) + where TPixel : struct, IPixel + { + Vector2 dpi = DefaultTextDpi; + if (options.UseImageResolution) + { + dpi = new Vector2((float)source.MetaData.HorizontalResolution, (float)source.MetaData.VerticalResolution); + } + + var style = new FontSpan(font, dpi) + { + ApplyKerning = options.ApplyKerning, + TabWidth = options.TabWidth, + WrappingWidth = options.WrapTextWidth, + HorizontalAlignment = options.HorizontalAlignment, + VerticalAlignment = options.VerticalAlignment + }; + + IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, path, style); + + var pathOptions = (GraphicsOptions)options; + if (brush != null) + { + source.Fill(brush, glyphs, pathOptions); + } + + if (pen != null) + { + source.Draw(pen, glyphs, pathOptions); + } + + return source; + } + } +} diff --git a/src/ImageSharp.Drawing/Text/DrawText.cs b/src/ImageSharp.Drawing/Text/DrawText.cs index 6bb87dcf5..3b0d3db41 100644 --- a/src/ImageSharp.Drawing/Text/DrawText.cs +++ b/src/ImageSharp.Drawing/Text/DrawText.cs @@ -183,7 +183,7 @@ namespace ImageSharp VerticalAlignment = options.VerticalAlignment }; - IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, style).Translate(location); // todo move to better API + IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, location, style); var pathOptions = (GraphicsOptions)options; if (brush != null) diff --git a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs b/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs deleted file mode 100644 index 5148236d8..000000000 --- a/tests/ImageSharp.Tests/Drawing/Paths/DrawPathCollection.cs +++ /dev/null @@ -1,179 +0,0 @@ - -namespace ImageSharp.Tests.Drawing.Paths -{ - using System; - - using ImageSharp.Drawing.Brushes; - - using Xunit; - using ImageSharp.Drawing; - using System.Numerics; - using SixLabors.Shapes; - using ImageSharp.Drawing.Processors; - using ImageSharp.Drawing.Pens; - using ImageSharp.PixelFormats; - - public class DrawPathCollection : IDisposable - { - float thickness = 7.2f; - GraphicsOptions noneDefault = new GraphicsOptions(); - Rgba32 color = Rgba32.HotPink; - SolidBrush brush = Brushes.Solid(Rgba32.HotPink); - Pen pen = new Pen(Rgba32.Gray, 99.9f); - IPath path1 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - - IPath path2 = new SixLabors.Shapes.Path(new LinearLineSegment(new Vector2[] { - new Vector2(10,10), - new Vector2(20,10), - new Vector2(20,10), - new Vector2(30,10), - })); - - IPathCollection pathCollection; - private ProcessorWatchingImage img; - - public DrawPathCollection() - { - this.pathCollection = new PathCollection(this.path1, this.path2); - this.img = new Paths.ProcessorWatchingImage(10, 10); - } - - public void Dispose() - { - img.Dispose(); - } - - [Fact] - public void CorrectlySetsBrushThicknessAndPath() - { - img.Draw(brush, thickness, pathCollection); - - Assert.NotEmpty(img.ProcessorApplications); - - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, this.pathCollection); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - } - - [Fact] - public void CorrectlySetsBrushThicknessPathAndOptions() - { - img.Draw(brush, thickness, pathCollection, noneDefault); - - Assert.NotEmpty(img.ProcessorApplications); - - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(brush, pen.Brush); - Assert.Equal(thickness, pen.Width); - } - } - - [Fact] - public void CorrectlySetsColorThicknessAndPath() - { - img.Draw(color, thickness, pathCollection); - - Assert.NotEmpty(img.ProcessorApplications); - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - } - - [Fact] - public void CorrectlySetsColorThicknessPathAndOptions() - { - img.Draw(color, thickness, pathCollection, noneDefault); - - Assert.Equal(2, img.ProcessorApplications.Count); - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Pen pen = Assert.IsType>(processor.Pen); - Assert.Equal(thickness, pen.Width); - - SolidBrush brush = Assert.IsType>(pen.Brush); - Assert.Equal(color, brush.Color); - } - } - - [Fact] - public void CorrectlySetsPenAndPath() - { - img.Draw(pen, pathCollection); - - Assert.Equal(2, img.ProcessorApplications.Count); - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(GraphicsOptions.Default, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Assert.Equal(pen, processor.Pen); - } - } - - [Fact] - public void CorrectlySetsPenPathAndOptions() - { - img.Draw(pen, pathCollection, noneDefault); - - Assert.Equal(2, img.ProcessorApplications.Count); - for (var i = 0; i < 2; i++) - { - DrawPathProcessor processor = Assert.IsType>(img.ProcessorApplications[i].processor); - - Assert.Equal(noneDefault, processor.Options); - - ShapePath shapepath = Assert.IsType(processor.Path); - Assert.Contains(shapepath.Path, pathCollection); - - Assert.Equal(pen, processor.Pen); - } - } - } -} diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawText.Path.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawText.Path.cs new file mode 100644 index 000000000..60fe44acd --- /dev/null +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawText.Path.cs @@ -0,0 +1,251 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Drawing.Text +{ + using System; + using System.Numerics; + + using ImageSharp.Drawing; + using ImageSharp.Drawing.Brushes; + using ImageSharp.Drawing.Pens; + using ImageSharp.Drawing.Processors; + using ImageSharp.PixelFormats; + using ImageSharp.Tests.Drawing.Paths; + + using SixLabors.Fonts; + using SixLabors.Shapes; + + using Xunit; + + public class DrawText_Path : IDisposable + { + Rgba32 color = Rgba32.HotPink; + + SolidBrush brush = Brushes.Solid(Rgba32.HotPink); + + IPath path = new SixLabors.Shapes.Path( + new LinearLineSegment( + new Vector2[] { new Vector2(10, 10), new Vector2(20, 10), new Vector2(20, 10), new Vector2(30, 10), })); + + private ProcessorWatchingImage img; + + private readonly FontCollection FontCollection; + + private readonly Font Font; + + public DrawText_Path() + { + this.FontCollection = new FontCollection(); + this.Font = this.FontCollection.Install(TestFontUtilities.GetPath("SixLaborsSampleAB.woff")); + this.img = new ProcessorWatchingImage(10, 10); + } + + public void Dispose() + { + this.img.Dispose(); + } + + [Fact] + public void FillsForEachACharachterWhenBrushSetAndNotPen() + { + this.img.DrawText( + "123", + this.Font, + Brushes.Solid(Rgba32.Red), + null, + path, + new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void FillsForEachACharachterWhenBrushSetAndNotPenDefaultOptions() + { + this.img.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), null, path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void FillsForEachACharachterWhenBrushSet() + { + this.img.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), path, new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void FillsForEachACharachterWhenBrushSetDefaultOptions() + { + this.img.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void FillsForEachACharachterWhenColorSet() + { + this.img.DrawText("123", this.Font, Rgba32.Red, path, new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); + FillRegionProcessor processor = + Assert.IsType>(this.img.ProcessorApplications[0].processor); + + SolidBrush brush = Assert.IsType>(processor.Brush); + Assert.Equal(Rgba32.Red, brush.Color); + } + + [Fact] + public void FillsForEachACharachterWhenColorSetDefaultOptions() + { + this.img.DrawText("123", this.Font, Rgba32.Red, path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); + Assert.IsType>(this.img.ProcessorApplications[0].processor); + FillRegionProcessor processor = + Assert.IsType>(this.img.ProcessorApplications[0].processor); + + SolidBrush brush = Assert.IsType>(processor.Brush); + Assert.Equal(Rgba32.Red, brush.Color); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetAndNotBrush() + { + this.img.DrawText( + "123", + this.Font, + null, + Pens.Dash(Rgba32.Red, 1), + path, + new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetAndNotBrushDefaultOptions() + { + this.img.DrawText("123", this.Font, null, Pens.Dash(Rgba32.Red, 1), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void DrawForEachACharachterWhenPenSet() + { + this.img.DrawText("123", this.Font, Pens.Dash(Rgba32.Red, 1), path, new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetDefaultOptions() + { + this.img.DrawText("123", this.Font, Pens.Dash(Rgba32.Red, 1), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(3, this.img.ProcessorApplications.Count); // 3 fills where applied + Assert.IsType>(this.img.ProcessorApplications[0].processor); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetAndFillFroEachWhenBrushSet() + { + this.img.DrawText( + "123", + this.Font, + Brushes.Solid(Rgba32.Red), + Pens.Dash(Rgba32.Red, 1), + path, + new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(6, this.img.ProcessorApplications.Count); + } + + [Fact] + public void DrawForEachACharachterWhenPenSetAndFillFroEachWhenBrushSetDefaultOptions() + { + this.img.DrawText("123", this.Font, Brushes.Solid(Rgba32.Red), Pens.Dash(Rgba32.Red, 1), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(6, this.img.ProcessorApplications.Count); + } + + [Fact] + public void BrushAppliesBeforPen() + { + this.img.DrawText( + "1", + this.Font, + Brushes.Solid(Rgba32.Red), + Pens.Dash(Rgba32.Red, 1), + path, + new TextGraphicsOptions(true)); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(2, this.img.ProcessorApplications.Count); + Assert.IsType>(this.img.ProcessorApplications[0].processor); + Assert.IsType>(this.img.ProcessorApplications[1].processor); + } + + [Fact] + public void BrushAppliesBeforPenDefaultOptions() + { + this.img.DrawText("1", this.Font, Brushes.Solid(Rgba32.Red), Pens.Dash(Rgba32.Red, 1), path); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(2, this.img.ProcessorApplications.Count); + Assert.IsType>(this.img.ProcessorApplications[0].processor); + Assert.IsType>(this.img.ProcessorApplications[1].processor); + } + + [Fact] + public void GlyphHeightChangesBasedOnuseImageResolutionFlag() + { + this.img.MetaData.VerticalResolution = 1; + this.img.MetaData.HorizontalResolution = 1; + this.img.DrawText("1", this.Font, Brushes.Solid(Rgba32.Red), path, new TextGraphicsOptions(true) { + UseImageResolution = false + }); + + this.img.DrawText("1", this.Font, Brushes.Solid(Rgba32.Red), path, new TextGraphicsOptions(true) + { + UseImageResolution = true + }); + + Assert.NotEmpty(this.img.ProcessorApplications); + Assert.Equal(2, this.img.ProcessorApplications.Count); + FillRegionProcessor ownResolution = Assert.IsType>(this.img.ProcessorApplications[0].processor); + FillRegionProcessor imgResolution = Assert.IsType>(this.img.ProcessorApplications[1].processor); + + ShapeRegion ownRegion = Assert.IsType(ownResolution.Region); + ShapeRegion imgRegion = Assert.IsType(imgResolution.Region); + + // magic numbers based on the font used at well known resolutions + Assert.Equal(7.44, ownRegion.Shape.Bounds.Height, 2); + Assert.Equal(0.1, imgRegion.Shape.Bounds.Height, 2); + } + } +} From ae1e2eda45b77c4915663be801c9205bf973f8da Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 1 Jun 2017 12:27:17 +1000 Subject: [PATCH 78/84] First attempt --- .../ResamplingWeightedProcessor.Weights.cs | 46 ++++++++++++++----- .../Transforms/ResizeProfilingBenchmarks.cs | 4 +- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs index b5266c9bd..9c37b69e6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs @@ -27,31 +27,54 @@ namespace ImageSharp.Processing.Processors public int Left; /// - /// The span of weights pointing to . + /// The length of the weights window /// - public Span Span; + public int Length; + + /// + /// The index in the destination buffer + /// + private readonly int destIndex; + + /// + /// The weights buffer . + /// + private readonly Buffer2D buffer; /// /// Initializes a new instance of the struct. /// + /// The destination index in the buffer /// The local left index - /// The span + /// The span + /// The length of the window [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal WeightsWindow(int left, Span span) + internal WeightsWindow(int index, int left, Buffer2D buffer, int length) { + this.destIndex = index; this.Left = left; - this.Span = span; + this.buffer = buffer; + this.Length = length; } /// - /// Gets an unsafe float* pointer to the beginning of . + /// Gets an unsafe float* pointer to the beginning of . /// - public ref float Ptr => ref this.Span.DangerousGetPinnableReference(); + public ref float Ptr + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + return ref this.GetWindowSpan().DangerousGetPinnableReference(); + } + } /// - /// Gets the lenghth of the weights window + /// Gets the span representing the portion of the that this window covers /// - public int Length => this.Span.Length; + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span GetWindowSpan() => this.buffer.GetRowSpan(this.destIndex).Slice(this.Left, this.Length); /// /// Computes the sum of vectors in 'rowSpan' weighted by weight values, pointed by this instance. @@ -139,7 +162,7 @@ namespace ImageSharp.Processing.Processors /// internal class WeightsBuffer : IDisposable { - private Buffer2D dataBuffer; + private readonly Buffer2D dataBuffer; /// /// Initializes a new instance of the class. @@ -174,8 +197,7 @@ namespace ImageSharp.Processing.Processors /// The weights public WeightsWindow GetWeightsWindow(int destIdx, int leftIdx, int rightIdx) { - Span span = this.dataBuffer.GetRowSpan(destIdx).Slice(leftIdx, rightIdx - leftIdx + 1); - return new WeightsWindow(leftIdx, span); + return new WeightsWindow(destIdx, leftIdx, this.dataBuffer, rightIdx - leftIdx + 1); } } } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs index 3f8a75b92..8b57586f4 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs @@ -5,6 +5,7 @@ namespace ImageSharp.Tests.Processing.Transforms { + using System; using System.IO; using System.Text; @@ -49,9 +50,10 @@ namespace ImageSharp.Tests.Processing.Transforms foreach (ResamplingWeightedProcessor.WeightsWindow window in weights.Weights) { + Span span = window.GetWindowSpan(); for (int i = 0; i < window.Length; i++) { - float value = window.Span[i]; + float value = span[i]; bld.Append(value); bld.Append("| "); } From 4ce6a0375897aa4255ac623483b2caa336250a34 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 1 Jun 2017 16:14:53 +1000 Subject: [PATCH 79/84] Add spec [skip ci] --- src/ImageSharp/Formats/Jpeg/itu-t81.pdf | Bin 0 -> 1058883 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/ImageSharp/Formats/Jpeg/itu-t81.pdf diff --git a/src/ImageSharp/Formats/Jpeg/itu-t81.pdf b/src/ImageSharp/Formats/Jpeg/itu-t81.pdf new file mode 100644 index 0000000000000000000000000000000000000000..83fba254b48936fbb8e0e3495c508089fd55408d GIT binary patch literal 1058883 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
8HTkqAgH&U7Y6ppR2#9;=0Bvt<@@S51Wx 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�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%0At5XPb&(O>a%OB?u@&=+S}f~ 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 Date: Thu, 1 Jun 2017 12:44:12 +0200 Subject: [PATCH 80/84] replaced WeightsWindow.destIndex with flatStartIndex --- .../ResamplingWeightedProcessor.Weights.cs | 27 +++++++++---------- .../Transforms/ResamplingWeightedProcessor.cs | 6 ++--- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs index 9c37b69e6..b7e2304fa 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs @@ -34,12 +34,12 @@ namespace ImageSharp.Processing.Processors ///

/// The index in the destination buffer /// - private readonly int destIndex; + private readonly int flatStartIndex; /// - /// The weights buffer . + /// The buffer containing the weights values. /// - private readonly Buffer2D buffer; + private readonly Buffer buffer; /// /// Initializes a new instance of the struct. @@ -51,22 +51,19 @@ namespace ImageSharp.Processing.Processors [MethodImpl(MethodImplOptions.AggressiveInlining)] internal WeightsWindow(int index, int left, Buffer2D buffer, int length) { - this.destIndex = index; + this.flatStartIndex = (index * buffer.Width) + left; this.Left = left; this.buffer = buffer; this.Length = length; } /// - /// Gets an unsafe float* pointer to the beginning of . + /// Gets a reference to the first item of the window. /// - public ref float Ptr + /// The reference to the first item of the window + public ref float GetStartReference() { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - return ref this.GetWindowSpan().DangerousGetPinnableReference(); - } + return ref this.buffer[this.flatStartIndex]; } /// @@ -74,7 +71,7 @@ namespace ImageSharp.Processing.Processors /// /// The [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Span GetWindowSpan() => this.buffer.GetRowSpan(this.destIndex).Slice(this.Left, this.Length); + public Span GetWindowSpan() => this.buffer.Slice(this.flatStartIndex, this.Length); /// /// Computes the sum of vectors in 'rowSpan' weighted by weight values, pointed by this instance. @@ -85,7 +82,7 @@ namespace ImageSharp.Processing.Processors [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ComputeWeightedRowSum(Span rowSpan, int sourceX) { - ref float horizontalValues = ref this.Ptr; + ref float horizontalValues = ref this.GetStartReference(); int left = this.Left; ref Vector4 vecPtr = ref Unsafe.Add(ref rowSpan.DangerousGetPinnableReference(), left + sourceX); @@ -112,7 +109,7 @@ namespace ImageSharp.Processing.Processors [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ComputeExpandedWeightedRowSum(Span rowSpan, int sourceX) { - ref float horizontalValues = ref this.Ptr; + ref float horizontalValues = ref this.GetStartReference(); int left = this.Left; ref Vector4 vecPtr = ref Unsafe.Add(ref rowSpan.DangerousGetPinnableReference(), left + sourceX); @@ -140,7 +137,7 @@ namespace ImageSharp.Processing.Processors [MethodImpl(MethodImplOptions.AggressiveInlining)] public Vector4 ComputeWeightedColumnSum(Buffer2D firstPassPixels, int x, int sourceY) { - ref float verticalValues = ref this.Ptr; + ref float verticalValues = ref this.GetStartReference(); int left = this.Left; // Destination color components diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs index 757b0889a..7245b961f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs @@ -112,7 +112,7 @@ namespace ImageSharp.Processing.Processors WeightsWindow ws = result.GetWeightsWindow(i, left, right); result.Weights[i] = ws; - ref float weights = ref ws.Ptr; + ref float weightsBaseRef = ref ws.GetStartReference(); for (int j = left; j <= right; j++) { @@ -120,7 +120,7 @@ namespace ImageSharp.Processing.Processors sum += weight; // weights[j - left] = weight: - Unsafe.Add(ref weights, j - left) = weight; + Unsafe.Add(ref weightsBaseRef, j - left) = weight; } // Normalise, best to do it here rather than in the pixel loop later on. @@ -129,7 +129,7 @@ namespace ImageSharp.Processing.Processors for (int w = 0; w < ws.Length; w++) { // weights[w] = weights[w] / sum: - ref float wRef = ref Unsafe.Add(ref weights, w); + ref float wRef = ref Unsafe.Add(ref weightsBaseRef, w); wRef = wRef / sum; } } From 0fd3f3bf24eab44dd0b83f626c9c74dd2b8fc03f Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Thu, 1 Jun 2017 12:51:50 +0200 Subject: [PATCH 81/84] inline all the things --- .../Processors/Transforms/ResamplingWeightedProcessor.Weights.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs index b7e2304fa..8aef87ec8 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs @@ -61,6 +61,7 @@ namespace ImageSharp.Processing.Processors /// Gets a reference to the first item of the window. /// /// The reference to the first item of the window + [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref float GetStartReference() { return ref this.buffer[this.flatStartIndex]; From 15dffecfc150ac3599513705db6779b034e9e42f Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Thu, 1 Jun 2017 22:17:55 +0100 Subject: [PATCH 82/84] ensure we fill pixels even if start is smaller then minX fixes #237 --- .../Processors/FillRegionProcessor.cs | 10 +++---- .../ImageSharp.Tests/Drawing/DrawPathTests.cs | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs index 8224b234d..f2e09d289 100644 --- a/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs @@ -154,13 +154,11 @@ namespace ImageSharp.Drawing.Processors int nextX = startX + 1; endX = Math.Min(endX, scanline.Length); // reduce to end to the right edge - if (nextX >= 0) + nextX = Math.Max(nextX, 0); + for (int x = nextX; x < endX; x++) { - for (int x = nextX; x < endX; x++) - { - scanline[x] += subpixelFraction; - scanlineDirty = true; - } + scanline[x] += subpixelFraction; + scanlineDirty = true; } } } diff --git a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs index a3911ac3e..4ba4a3a83 100644 --- a/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs +++ b/tests/ImageSharp.Tests/Drawing/DrawPathTests.cs @@ -13,6 +13,7 @@ namespace ImageSharp.Tests.Drawing using ImageSharp.PixelFormats; using Xunit; + using ImageSharp.Drawing.Pens; public class DrawPathTests : FileTestBase { @@ -98,5 +99,32 @@ namespace ImageSharp.Tests.Drawing } } + + [Fact] + public void PathExtendingOffEdgeOfImageShouldNotBeCropped() + { + + string path = this.CreateOutputDirectory("Drawing", "Path"); + using (var image = new Image(256, 256)) + { + image.Fill(Rgba32.Black); + var pen = Pens.Solid(Rgba32.White, 5f); + + for (int i = 0; i < 300; i += 20) + { + image.DrawLines(pen, new Vector2[] { new Vector2(100, 2), new Vector2(-10, i) }); + } + + using (FileStream output = File.OpenWrite($"{path}/ClippedLines.png")) + { + image + .Save(output); + } + using (PixelAccessor sourcePixels = image.Lock()) + { + Assert.Equal(Rgba32.White, sourcePixels[0, 90]); + } + } + } } } \ No newline at end of file From ee8f510e640ca06fb542559a0f7090328a091ed9 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Thu, 1 Jun 2017 22:48:41 +0100 Subject: [PATCH 83/84] ensure we consume stream when failing to read ICC profile --- src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index 13c51db24..d65c095da 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -982,6 +982,7 @@ namespace ImageSharp.Formats byte[] identifier = new byte[Icclength]; this.InputProcessor.ReadFull(identifier, 0, Icclength); + remaining -= Icclength; // we have read it by this point if (identifier[0] == 'I' && identifier[1] == 'C' && @@ -996,7 +997,6 @@ namespace ImageSharp.Formats identifier[10] == 'E' && identifier[11] == '\0') { - remaining -= Icclength; byte[] profile = new byte[remaining]; this.InputProcessor.ReadFull(profile, 0, remaining); @@ -1009,6 +1009,11 @@ namespace ImageSharp.Formats metadata.IccProfile.Extend(profile); } } + else + { + // not an ICC profile we can handle read the remaining so we can carry on and ignore this. + this.InputProcessor.Skip(remaining); + } } /// From 3b9e332da36bbdff06f7996b509ef598d2688882 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Fri, 2 Jun 2017 18:51:49 +0100 Subject: [PATCH 84/84] update to latest Shapes release --- src/ImageSharp.Drawing/ImageSharp.Drawing.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj index 9d24c1777..13500b65a 100644 --- a/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj +++ b/src/ImageSharp.Drawing/ImageSharp.Drawing.csproj @@ -36,7 +36,7 @@ - + All