From 74f05629b86d7b4e9d30266d5a0b3c5acbc8ba2d Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Tue, 5 Sep 2017 21:07:14 +0100 Subject: [PATCH] fix frame double processing moved some extensions into new namespace --- .../Processors/DrawImageProcessor.cs | 2 + .../Processors/FillProcessor.cs | 6 +- src/ImageSharp/Advanced/ImageExtensions.cs | 37 +++++- src/ImageSharp/ApplyProcessors.cs | 9 +- .../DefaultInternalImageProcessorContext.cs | 1 + src/ImageSharp/Formats/Bmp/ImageExtensions.cs | 3 +- src/ImageSharp/Formats/Gif/ImageExtensions.cs | 3 +- .../Common/Decoder/JpegImagePostProcessor.cs | 1 + .../Formats/Jpeg/ImageExtensions.cs | 3 +- src/ImageSharp/Formats/Png/ImageExtensions.cs | 3 +- src/ImageSharp/Helpers/ImageExtensions.cs | 63 ++++++++++ src/ImageSharp/Image/ImageExtensions.cs | 108 +++++++++--------- .../Image/ImageFrame.LoadPixelData.cs | 54 +++++++++ src/ImageSharp/Image/ImageFrameCollection.cs | 23 +++- src/ImageSharp/Image/ImageFrame{TPixel}.cs | 19 +-- src/ImageSharp/Image/Image{TPixel}.cs | 21 ++-- src/ImageSharp/Image/PixelAccessor{TPixel}.cs | 3 +- .../ErrorDiffusionDitherProcessor.cs | 1 + .../Binarization/OrderedDitherProcessor.cs | 1 + .../Convolution/Convolution2PassProcessor.cs | 2 + .../EdgeDetectorCompassProcessor.cs | 1 + .../Processing/Processors/ImageProcessor.cs | 4 - .../Processors/Overlays/GlowProcessor.cs | 1 + .../Processors/Overlays/VignetteProcessor.cs | 1 + .../Processors/Transforms/ResizeProcessor.cs | 3 +- .../Processors/Transforms/RotateProcessor.cs | 1 + .../Processors/Transforms/SkewProcessor.cs | 2 + src/ImageSharp/Quantizers/Quantize.cs | 3 +- tests/ImageSharp.Benchmarks/Samplers/Glow.cs | 6 +- .../Image/ImageRotationTests.cs | 5 +- .../Processors/Transforms/ResizeTests.cs | 1 + tests/ImageSharp.Tests/TestFile.cs | 3 +- .../ImageComparison/ExactImageComparer.cs | 1 + .../ImageComparison/ImageComparer.cs | 2 +- .../ImageComparison/TolerantImageComparer.cs | 1 + 35 files changed, 283 insertions(+), 115 deletions(-) create mode 100644 src/ImageSharp/Helpers/ImageExtensions.cs create mode 100644 src/ImageSharp/Image/ImageFrame.LoadPixelData.cs diff --git a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs index 2a8e2cf4c..25eddaf0b 100644 --- a/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs @@ -4,6 +4,8 @@ using System; using System.Numerics; using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; diff --git a/src/ImageSharp.Drawing/Processors/FillProcessor.cs b/src/ImageSharp.Drawing/Processors/FillProcessor.cs index 57c4e3d9b..3c0883d66 100644 --- a/src/ImageSharp.Drawing/Processors/FillProcessor.cs +++ b/src/ImageSharp.Drawing/Processors/FillProcessor.cs @@ -4,6 +4,7 @@ using System; using System.Numerics; using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Drawing; using SixLabors.ImageSharp.Drawing.Brushes; using SixLabors.ImageSharp.Drawing.Brushes.Processors; @@ -64,10 +65,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors } int width = maxX - minX; - - // 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 (var amount = new Buffer(width)) using (BrushApplicator applicator = this.brush.CreateApplicator(source, sourceRectangle, this.options)) { diff --git a/src/ImageSharp/Advanced/ImageExtensions.cs b/src/ImageSharp/Advanced/ImageExtensions.cs index 1bd7c0cc4..d3d563fae 100644 --- a/src/ImageSharp/Advanced/ImageExtensions.cs +++ b/src/ImageSharp/Advanced/ImageExtensions.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Advanced /// The public static Span GetPixelRowSpan(this ImageFrame source, int row) where TPixel : struct, IPixel - => GetSpan(source).Slice(row * source.Width, source.Width); + => GetSpan(source, row); /// /// Gets a representing the row 'y' beginning from the the first pixel on that row. @@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Advanced /// The public static Span GetPixelRowSpan(this Image source, int row) where TPixel : struct, IPixel - => GetSpan(source).Slice(row * source.Width, source.Width); + => GetSpan(source, row); /// /// Gets the span. @@ -67,5 +67,38 @@ namespace SixLabors.ImageSharp.Advanced private static Span GetSpan(IImageFrame source) where TPixel : struct, IPixel => source.PixelBuffer.Span; + + /// + /// Gets the span. + /// + /// The type of the pixel. + /// The source. + /// The row. + /// + /// The span retuned from Pixel source + /// + private static Span GetSpan(IImageFrame source, int row) + where TPixel : struct, IPixel + => source.PixelBuffer.Span.Slice(row * source.Width, source.Width); + + /// + /// Gets the bounds of the image. + /// + /// The Pixel format. + /// The source image + /// Returns the bounds of the image + public static Configuration Configuration(this ImageFrame source) + where TPixel : struct, IPixel + => source?.Parent?.ImageConfiguration ?? SixLabors.ImageSharp.Configuration.Default; + + /// + /// Gets the bounds of the image. + /// + /// The Pixel format. + /// The source image + /// Returns the bounds of the image + public static Configuration Configuration(this Image source) + where TPixel : struct, IPixel + => source?.ImageConfiguration ?? SixLabors.ImageSharp.Configuration.Default; } } diff --git a/src/ImageSharp/ApplyProcessors.cs b/src/ImageSharp/ApplyProcessors.cs index 178833275..3184bc592 100644 --- a/src/ImageSharp/ApplyProcessors.cs +++ b/src/ImageSharp/ApplyProcessors.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; @@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(operation, nameof(operation)); Guard.NotNull(source, nameof(source)); - IInternalImageProcessingContext operationsRunner = source.Configuration.ImageOperationsProvider.CreateImageProcessingContext(source, true); + IInternalImageProcessingContext operationsRunner = source.Configuration().ImageOperationsProvider.CreateImageProcessingContext(source, true); operation(operationsRunner); operationsRunner.Apply(); } @@ -41,7 +42,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(operations, nameof(operations)); Guard.NotNull(source, nameof(source)); - IInternalImageProcessingContext operationsRunner = source.Configuration.ImageOperationsProvider.CreateImageProcessingContext(source, true); + IInternalImageProcessingContext operationsRunner = source.Configuration().ImageOperationsProvider.CreateImageProcessingContext(source, true); operationsRunner.ApplyProcessors(operations); operationsRunner.Apply(); } @@ -59,7 +60,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(operation, nameof(operation)); Guard.NotNull(source, nameof(source)); - IInternalImageProcessingContext operationsRunner = source.Configuration.ImageOperationsProvider.CreateImageProcessingContext(source, false); + IInternalImageProcessingContext operationsRunner = source.Configuration().ImageOperationsProvider.CreateImageProcessingContext(source, false); operation(operationsRunner); return operationsRunner.Apply(); } @@ -77,7 +78,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(operations, nameof(operations)); Guard.NotNull(source, nameof(source)); - IInternalImageProcessingContext operationsRunner = source.Configuration.ImageOperationsProvider.CreateImageProcessingContext(source, false); + IInternalImageProcessingContext operationsRunner = source.Configuration().ImageOperationsProvider.CreateImageProcessingContext(source, false); operationsRunner.ApplyProcessors(operations); return operationsRunner.Apply(); } diff --git a/src/ImageSharp/DefaultInternalImageProcessorContext.cs b/src/ImageSharp/DefaultInternalImageProcessorContext.cs index 8eb1c09fe..2e2602d3c 100644 --- a/src/ImageSharp/DefaultInternalImageProcessorContext.cs +++ b/src/ImageSharp/DefaultInternalImageProcessorContext.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.Primitives; diff --git a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs index 558ce69c5..3bcbed49a 100644 --- a/src/ImageSharp/Formats/Bmp/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Bmp/ImageExtensions.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.PixelFormats; @@ -35,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsBmp(this Image source, Stream stream, BmpEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.Configuration.FindEncoder(ImageFormats.Bmp)); + => source.Save(stream, encoder ?? source.Configuration().FindEncoder(ImageFormats.Bmp)); } } diff --git a/src/ImageSharp/Formats/Gif/ImageExtensions.cs b/src/ImageSharp/Formats/Gif/ImageExtensions.cs index b5f358f58..8174ec6f4 100644 --- a/src/ImageSharp/Formats/Gif/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Gif/ImageExtensions.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.PixelFormats; @@ -35,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsGif(this Image source, Stream stream, GifEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.Configuration.FindEncoder(ImageFormats.Gif)); + => source.Save(stream, encoder ?? source.Configuration().FindEncoder(ImageFormats.Gif)); } } diff --git a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs index 52fc1c228..e3ca1d74c 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs @@ -2,6 +2,7 @@ using System; using System.Linq; using System.Numerics; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs index c7d7b26da..bc87b3a1b 100644 --- a/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Jpeg/ImageExtensions.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.PixelFormats; @@ -35,6 +36,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsJpeg(this Image source, Stream stream, JpegEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.Configuration.FindEncoder(ImageFormats.Jpeg)); + => source.Save(stream, encoder ?? source.Configuration().FindEncoder(ImageFormats.Jpeg)); } } diff --git a/src/ImageSharp/Formats/Png/ImageExtensions.cs b/src/ImageSharp/Formats/Png/ImageExtensions.cs index 5d7539915..e237d6a4e 100644 --- a/src/ImageSharp/Formats/Png/ImageExtensions.cs +++ b/src/ImageSharp/Formats/Png/ImageExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System.IO; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; @@ -34,6 +35,6 @@ namespace SixLabors.ImageSharp /// Thrown if the stream is null. public static void SaveAsPng(this Image source, Stream stream, PngEncoder encoder) where TPixel : struct, IPixel - => source.Save(stream, encoder ?? source.Configuration.FindEncoder(ImageFormats.Png)); + => source.Save(stream, encoder ?? source.Configuration().FindEncoder(ImageFormats.Png)); } } diff --git a/src/ImageSharp/Helpers/ImageExtensions.cs b/src/ImageSharp/Helpers/ImageExtensions.cs new file mode 100644 index 000000000..9f3d29332 --- /dev/null +++ b/src/ImageSharp/Helpers/ImageExtensions.cs @@ -0,0 +1,63 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Helpers +{ + /// + /// Extension methods over Image{TPixel} + /// + public static partial class ImageExtensions + { + + /// + /// Gets the bounds of the image. + /// + /// The Pixel format. + /// The source image + /// Returns the bounds of the image + public static Rectangle Bounds(this Image source) + where TPixel : struct, IPixel + => new Rectangle(0, 0, source.Width, source.Height); + + /// + /// Gets the bounds of the image. + /// + /// The Pixel format. + /// The source image + /// Returns the bounds of the image + public static Rectangle Bounds(this ImageFrame source) + where TPixel : struct, IPixel + => new Rectangle(0, 0, source.Width, source.Height); + + /// + /// Gets the size of the image. + /// + /// The Pixel format. + /// The source image + /// Returns the bounds of the image + public static Size Size(this Image source) + where TPixel : struct, IPixel + => new Size(source.Width, source.Height); + + /// + /// Gets the size of the image. + /// + /// The Pixel format. + /// The source image + /// Returns the bounds of the image + public static Size Size(this ImageFrame source) + where TPixel : struct, IPixel + => new Size(source.Width, source.Height); + + } +} diff --git a/src/ImageSharp/Image/ImageExtensions.cs b/src/ImageSharp/Image/ImageExtensions.cs index 9c7b0962e..8e78de056 100644 --- a/src/ImageSharp/Image/ImageExtensions.cs +++ b/src/ImageSharp/Image/ImageExtensions.cs @@ -18,56 +18,6 @@ namespace SixLabors.ImageSharp /// public static partial class ImageExtensions { - /// - /// Gets the bounds of the image. - /// - /// The Pixel format. - /// The source image - /// Returns the bounds of the image - public static Configuration Configuration(this ImageFrame source) - where TPixel : struct, IPixel - => source.Parent?.Configuration ?? SixLabors.ImageSharp.Configuration.Default; - - /// - /// Gets the bounds of the image. - /// - /// The Pixel format. - /// The source image - /// Returns the bounds of the image - public static Rectangle Bounds(this Image source) - where TPixel : struct, IPixel - => new Rectangle(0, 0, source.Width, source.Height); - - /// - /// Gets the bounds of the image. - /// - /// The Pixel format. - /// The source image - /// Returns the bounds of the image - public static Rectangle Bounds(this ImageFrame source) - where TPixel : struct, IPixel - => new Rectangle(0, 0, source.Width, source.Height); - - /// - /// Gets the size of the image. - /// - /// The Pixel format. - /// The source image - /// Returns the bounds of the image - public static Size Size(this Image source) - where TPixel : struct, IPixel - => new Size(source.Width, source.Height); - - /// - /// Gets the size of the image. - /// - /// The Pixel format. - /// The source image - /// Returns the bounds of the image - public static Size Size(this ImageFrame source) - where TPixel : struct, IPixel - => new Size(source.Width, source.Height); - #if !NETSTANDARD1_1 /// /// Saves the image to the given stream using the currently loaded image format. @@ -82,12 +32,12 @@ namespace SixLabors.ImageSharp Guard.NotNullOrEmpty(filePath, nameof(filePath)); string ext = Path.GetExtension(filePath).Trim('.'); - IImageFormat format = source.Configuration.FindFormatByFileExtension(ext); + IImageFormat format = source.Configuration().FindFormatByFileExtension(ext); if (format == null) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Can't find a format that is associated with the file extention '{ext}'. Registered formats with there extensions include:"); - foreach (IImageFormat fmt in source.Configuration.ImageFormats) + foreach (IImageFormat fmt in source.Configuration().ImageFormats) { stringBuilder.AppendLine($" - {fmt.Name} : {string.Join(", ", fmt.FileExtensions)}"); } @@ -95,13 +45,13 @@ namespace SixLabors.ImageSharp throw new NotSupportedException(stringBuilder.ToString()); } - IImageEncoder encoder = source.Configuration.FindEncoder(format); + IImageEncoder encoder = source.Configuration().FindEncoder(format); if (encoder == null) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Can't find encoder for file extention '{ext}' using image format '{format.Name}'. Registered encoders include:"); - foreach (KeyValuePair enc in source.Configuration.ImageEncoders) + foreach (KeyValuePair enc in source.Configuration().ImageEncoders) { stringBuilder.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}"); } @@ -124,7 +74,7 @@ namespace SixLabors.ImageSharp where TPixel : struct, IPixel { Guard.NotNull(encoder, nameof(encoder)); - using (Stream fs = source.Configuration.FileSystem.Create(filePath)) + using (Stream fs = source.Configuration().FileSystem.Create(filePath)) { source.Save(fs, encoder); } @@ -143,14 +93,14 @@ namespace SixLabors.ImageSharp where TPixel : struct, IPixel { Guard.NotNull(format, nameof(format)); - IImageEncoder encoder = source.Configuration.FindEncoder(format); + IImageEncoder encoder = source.Configuration().FindEncoder(format); if (encoder == null) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine("Can't find encoder for provided mime type. Available encoded:"); - foreach (KeyValuePair val in source.Configuration.ImageEncoders) + foreach (KeyValuePair val in source.Configuration().ImageEncoders) { stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}"); } @@ -161,6 +111,28 @@ namespace SixLabors.ImageSharp source.Save(stream, encoder); } + /// + /// Saves the raw image to the given bytes. + /// + /// The Pixel format. + /// The source image + /// A copy of the pixel data as bytes from this frame. + /// Thrown if the stream is null. + public static byte[] SavePixelData(this ImageFrame source) + where TPixel : struct, IPixel + => source.GetPixelSpan().AsBytes().ToArray(); + + /// + /// Saves the raw image to the given bytes. + /// + /// The Pixel format. + /// The source image + /// The buffer to save the raw pixel data to. + /// Thrown if the stream is null. + public static void SavePixelData(this ImageFrame source, byte[] buffer) + where TPixel : struct, IPixel + => SavePixelData(source, new Span(buffer)); + /// /// Saves the raw image to the given bytes. /// @@ -177,6 +149,28 @@ namespace SixLabors.ImageSharp byteBuffer.CopyTo(buffer); } + /// + /// Saves the raw image to the given bytes. + /// + /// The Pixel format. + /// The source image + /// A copy of the pixel data from the first frame as bytes. + /// Thrown if the stream is null. + public static byte[] SavePixelData(this Image source) + where TPixel : struct, IPixel + => source.GetPixelSpan().AsBytes().ToArray(); + + /// + /// Saves the raw image to the given bytes. + /// + /// The Pixel format. + /// The source image + /// The buffer to save the raw pixel data to. + /// Thrown if the stream is null. + public static void SavePixelData(this Image source, byte[] buffer) + where TPixel : struct, IPixel + => SavePixelData(source, new Span(buffer)); + /// /// Saves the raw image to the given bytes. /// diff --git a/src/ImageSharp/Image/ImageFrame.LoadPixelData.cs b/src/ImageSharp/Image/ImageFrame.LoadPixelData.cs new file mode 100644 index 000000000..3f63b9c64 --- /dev/null +++ b/src/ImageSharp/Image/ImageFrame.LoadPixelData.cs @@ -0,0 +1,54 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + /// + /// Adds static methods allowing the creation of new image from raw pixel data. + /// + public static partial class ImageFrame + { + /// + /// 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. + /// The width of the final image. + /// The height of the final image. + /// The pixel format. + /// A new . + public static ImageFrame LoadPixelData(Span data, int width, int height) + where TPixel : struct, IPixel + => LoadPixelData(data.NonPortableCast(), width, height); + + /// + /// Create a new instance of the class from the raw 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 . + public static ImageFrame LoadPixelData(Span data, int width, int height) + where TPixel : struct, IPixel + { + int count = width * height; + Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data)); + + var image = new ImageFrame(width, height); + SpanHelper.Copy(data, image.GetPixelSpan(), count); + + return image; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Image/ImageFrameCollection.cs b/src/ImageSharp/Image/ImageFrameCollection.cs index 186f94762..92e068ec8 100644 --- a/src/ImageSharp/Image/ImageFrameCollection.cs +++ b/src/ImageSharp/Image/ImageFrameCollection.cs @@ -37,6 +37,22 @@ namespace SixLabors.ImageSharp /// public int Count { get => this.frames.Count; } + /// + /// Gets the root frame. + /// + public ImageFrame RootFrame + { + get + { + if (this.frames.Count > 0) + { + return this.frames[0]; + } + + return null; + } + } + /// /// Gets or sets the at the specified index. /// @@ -105,9 +121,12 @@ namespace SixLabors.ImageSharp private void ValidateFrameSize(ImageFrame frame) { - if (this.parent.Width != frame.Width || this.parent.Height != frame.Height) + if (this.Count != 0) { - throw new ArgumentException("Frame must have the same dimensions as the image", nameof(frame)); + if (this.parent.Width != frame.Width || this.parent.Height != frame.Height) + { + throw new ArgumentException("Frame must have the same dimensions as the image", nameof(frame)); + } } } diff --git a/src/ImageSharp/Image/ImageFrame{TPixel}.cs b/src/ImageSharp/Image/ImageFrame{TPixel}.cs index cc5c8b1ac..9d6b945ab 100644 --- a/src/ImageSharp/Image/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/Image/ImageFrame{TPixel}.cs @@ -49,8 +49,6 @@ namespace SixLabors.ImageSharp Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.NotNull(metaData, nameof(metaData)); - this.Width = width; - this.Height = height; this.pixelBuffer = Buffer2D.CreateClean(width, height); this.MetaData = metaData; } @@ -61,9 +59,7 @@ namespace SixLabors.ImageSharp /// The source. internal ImageFrame(ImageFrame source) { - this.Width = source.Width; - this.Height = source.Height; - this.pixelBuffer = new Buffer2D(source.Width, source.Height); + this.pixelBuffer = new Buffer2D(source.pixelBuffer.Width, source.pixelBuffer.Height); source.pixelBuffer.Span.CopyTo(this.pixelBuffer.Span); this.MetaData = source.MetaData.Clone(); } @@ -72,10 +68,10 @@ namespace SixLabors.ImageSharp Buffer2D IImageFrame.PixelBuffer => this.pixelBuffer; /// - public int Width { get; private set; } + public int Width => this.pixelBuffer.Width; /// - public int Height { get; private set; } + public int Height => this.pixelBuffer.Height; /// /// Gets the configuration providing initialization code which allows extending the library. @@ -158,13 +154,8 @@ namespace SixLabors.ImageSharp { Guard.NotNull(pixelSource, nameof(pixelSource)); - int newWidth = pixelSource.Width; - int newHeight = pixelSource.Height; - // Push my memory into the accessor (which in turn unpins the old buffer ready for the images use) var newPixels = pixelSource.SwapBufferOwnership(this.pixelBuffer); - this.Width = newWidth; - this.Height = newHeight; this.pixelBuffer = newPixels; } @@ -181,11 +172,7 @@ namespace SixLabors.ImageSharp var newPixels = pixelSource.pixelBuffer; pixelSource.pixelBuffer = this.pixelBuffer; - pixelSource.Width = this.Width; - pixelSource.Height = this.Height; - this.Width = newWidth; - this.Height = newHeight; this.pixelBuffer = newPixels; } diff --git a/src/ImageSharp/Image/Image{TPixel}.cs b/src/ImageSharp/Image/Image{TPixel}.cs index 94d6ddb6a..ce8a6f721 100644 --- a/src/ImageSharp/Image/Image{TPixel}.cs +++ b/src/ImageSharp/Image/Image{TPixel}.cs @@ -75,8 +75,6 @@ namespace SixLabors.ImageSharp { Guard.NotNull(pixelSource, nameof(pixelSource)); - this.Width = pixelSource.Width; - this.Height = pixelSource.Height; int newHeight = pixelSource.Height; for (int i = 0; i < this.Frames.Count; i++) @@ -85,7 +83,6 @@ namespace SixLabors.ImageSharp } } - /// /// Initializes a new instance of the class /// with the height and the width of the image. @@ -97,9 +94,7 @@ namespace SixLabors.ImageSharp /// The frames that will be owned by this image instance. internal Image(Configuration configuration, int width, int height, ImageMetaData metadata, IEnumerable> frames) { - this.Configuration = configuration ?? Configuration.Default; - this.Width = width; - this.Height = height; + this.ImageConfiguration = configuration ?? Configuration.Default; this.MetaData = metadata ?? new ImageMetaData(); this.Frames = new ImageFrameCollection(this); @@ -114,7 +109,7 @@ namespace SixLabors.ImageSharp if (this.Frames.Count == 0) { - this.Frames.Add(new ImageFrame(this.Width, this.Height)); + this.Frames.Add(new ImageFrame(width, height)); } } @@ -124,17 +119,17 @@ namespace SixLabors.ImageSharp /// /// The configuration. /// - public Configuration Configuration { get; } + internal Configuration ImageConfiguration { get; } /// /// Gets the width. /// - public int Width { get; private set; } + public int Width => this.RootFrame?.Width ?? 0; /// /// Gets the height. /// - public int Height { get; private set; } + public int Height => this.RootFrame?.Height ?? 0; /// /// Gets the meta data of the image. @@ -149,7 +144,7 @@ namespace SixLabors.ImageSharp /// /// Gets the root frame. /// - private IImageFrame RootFrame => this.Frames[0]; + private IImageFrame RootFrame => this.Frames.RootFrame; /// Buffer2D IImageFrame.PixelBuffer => this.RootFrame.PixelBuffer; @@ -201,7 +196,7 @@ namespace SixLabors.ImageSharp { IEnumerable> frames = this.Frames.Select(x => x.Clone()).ToArray(); - return new Image(this.Configuration, this.Width, this.Height, this.MetaData.Clone(), frames); + return new Image(this.ImageConfiguration, this.Width, this.Height, this.MetaData.Clone(), frames); } /// @@ -219,7 +214,7 @@ namespace SixLabors.ImageSharp where TPixel2 : struct, IPixel { IEnumerable> frames = this.Frames.Select(x => x.CloneAs()).ToArray(); - var target = new Image(this.Configuration, this.Width, this.Height, this.MetaData, frames); + var target = new Image(this.ImageConfiguration, this.Width, this.Height, this.MetaData, frames); return target; } diff --git a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs index 0204c9e77..006429a17 100644 --- a/src/ImageSharp/Image/PixelAccessor{TPixel}.cs +++ b/src/ImageSharp/Image/PixelAccessor{TPixel}.cs @@ -5,6 +5,7 @@ using System; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using Unsafe = System.Runtime.CompilerServices.Unsafe; @@ -48,7 +49,7 @@ namespace SixLabors.ImageSharp Guard.MustBeGreaterThan(image.Height, 0, "image height"); this.SetPixelBufferUnsafe(image.PixelBuffer, false); - Configuration config = image.Parent?.Configuration ?? Configuration.Default; + Configuration config = image.Parent.Configuration(); this.ParallelOptions = config.ParallelOptions; } diff --git a/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs index d2a68094e..719a7ea34 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs @@ -4,6 +4,7 @@ using System; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Dithering; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs index c4499a372..d8b132c6c 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs @@ -5,6 +5,7 @@ using System; using System.Buffers; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Dithering; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs index d6efce35b..1aeb37862 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs @@ -4,6 +4,8 @@ using System; using System.Numerics; using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs index 86f33c345..bbe527eb7 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs @@ -4,6 +4,7 @@ using System; using System.Numerics; using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/ImageProcessor.cs b/src/ImageSharp/Processing/Processors/ImageProcessor.cs index ed1ec1c29..46f8f2525 100644 --- a/src/ImageSharp/Processing/Processors/ImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/ImageProcessor.cs @@ -22,10 +22,6 @@ namespace SixLabors.ImageSharp.Processing { this.BeforeImageApply(source, sourceRectangle); - this.BeforeApply(source, sourceRectangle); - this.OnApply(source, sourceRectangle); - this.AfterApply(source, sourceRectangle); - foreach (ImageFrame sourceFrame in source.Frames) { this.BeforeApply(sourceFrame, sourceRectangle); diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs index eeb9ae8e8..d8a611c0f 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs @@ -5,6 +5,7 @@ using System; using System.Numerics; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs index 7d3da8c89..c9bfc27cf 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs @@ -5,6 +5,7 @@ using System; using System.Numerics; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs index a56afd450..d50a68def 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs @@ -52,12 +52,13 @@ namespace SixLabors.ImageSharp.Processing.Processors /// protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { + var config = source.Configuration(); // We will always be creating the clone even for mutate because thats the way this base processor works // ------------ // For resize we know we are going to populate every pixel with fresh data and we want a different target size so // let's manually clone an empty set of images at the correct target and then have the base class processs them in turn. var frames = source.Frames.Select(x => new ImageFrame(this.Width, this.Height, x.MetaData.Clone())); // this will create places holders - var image = new Image(source.Configuration, this.Width, this.Height, source.MetaData.Clone(), frames); // base the place holder images in to prevet a extra frame being added + var image = new Image(config, this.Width, this.Height, source.MetaData.Clone(), frames); // base the place holder images in to prevet a extra frame being added return image; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs index be865be0a..43bf19d49 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs @@ -5,6 +5,7 @@ using System; using System.Numerics; using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs index 5d4578e8c..bafda41db 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs @@ -4,6 +4,8 @@ using System; using System.Numerics; using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/src/ImageSharp/Quantizers/Quantize.cs b/src/ImageSharp/Quantizers/Quantize.cs index 26d37615b..d9c3c84cd 100644 --- a/src/ImageSharp/Quantizers/Quantize.cs +++ b/src/ImageSharp/Quantizers/Quantize.cs @@ -3,6 +3,7 @@ using System; using System.Threading.Tasks; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Quantizers; @@ -65,7 +66,7 @@ namespace SixLabors.ImageSharp Parallel.For( 0, pixels.Height, - img.Configuration.ParallelOptions, + img.Configuration().ParallelOptions, y => { for (int x = 0; x < pixels.Width; x++) diff --git a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs index 64eb9e8b5..39a6e9211 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Glow.cs +++ b/tests/ImageSharp.Benchmarks/Samplers/Glow.cs @@ -17,6 +17,8 @@ namespace SixLabors.ImageSharp.Benchmarks using SixLabors.ImageSharp.Memory; using SixLabors.Primitives; + using SixLabors.ImageSharp.Helpers; + using SixLabors.ImageSharp.Advanced; public class Glow : BenchmarkBase { @@ -35,7 +37,7 @@ namespace SixLabors.ImageSharp.Benchmarks { using (Image image = new Image(800, 800)) { - bulk.Apply(image, image.Bounds()); + this.bulk.Apply(image, image.Bounds()); return new CoreSize(image.Width, image.Height); } } @@ -45,7 +47,7 @@ namespace SixLabors.ImageSharp.Benchmarks { using (Image image = new Image(800, 800)) { - parallel.Apply(image, image.Bounds()); + this.parallel.Apply(image, image.Bounds()); return new CoreSize(image.Width, image.Height); } } diff --git a/tests/ImageSharp.Tests/Image/ImageRotationTests.cs b/tests/ImageSharp.Tests/Image/ImageRotationTests.cs index 0e7dc5917..73c2f78f4 100644 --- a/tests/ImageSharp.Tests/Image/ImageRotationTests.cs +++ b/tests/ImageSharp.Tests/Image/ImageRotationTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.Helpers; using SixLabors.Primitives; using Xunit; @@ -48,9 +49,9 @@ namespace SixLabors.ImageSharp.Tests var file = TestFile.Create(TestImages.Bmp.Car); using (var image = Image.Load(file.FullPath)) { - Size original = image.Bounds().Size; + Size original = image.Size(); image.Mutate(x => x.Rotate(angle)); - return (original, image.Bounds().Size); + return (original, image.Size()); } } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 99520d887..820ca8356 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; diff --git a/tests/ImageSharp.Tests/TestFile.cs b/tests/ImageSharp.Tests/TestFile.cs index f56802e54..e77b95f9e 100644 --- a/tests/ImageSharp.Tests/TestFile.cs +++ b/tests/ImageSharp.Tests/TestFile.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.PixelFormats; @@ -145,7 +146,7 @@ namespace SixLabors.ImageSharp.Tests /// public Image CreateImage(IImageDecoder decoder) { - return ImageSharp.Image.Load(this.Image.Configuration, this.Bytes, decoder); + return ImageSharp.Image.Load(this.Image.Configuration(), this.Bytes, decoder); } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs index 521d30fd9..86c5994db 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs @@ -3,6 +3,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison using System; using System.Collections.Generic; using SixLabors.ImageSharp.Advanced; + using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs index effebdecf..8378db4e3 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; - +using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; diff --git a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs index 9688262d0..828c669d5 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs @@ -5,6 +5,7 @@ using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; + using SixLabors.ImageSharp.Helpers; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives;