diff --git a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
index dc55112c9..e217fd9a6 100644
--- a/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
+++ b/src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
diff --git a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
index 4b1d4222c..22e6d47e9 100644
--- a/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
+++ b/src/ImageSharp/Advanced/AdvancedImageExtensions.cs
@@ -15,6 +15,15 @@ namespace SixLabors.ImageSharp.Advanced
///
public static class AdvancedImageExtensions
{
+ ///
+ /// Accepts a to implement a double-dispatch pattern in order to
+ /// apply pixel-specific operations on non-generic instances
+ ///
+ /// The source.
+ /// The visitor.
+ public static void AcceptVisitor(this Image source, IImageVisitor visitor)
+ => source.Accept(visitor);
+
///
/// Gets the configuration for the image.
///
diff --git a/src/ImageSharp/IImageVisitor.cs b/src/ImageSharp/Advanced/IImageVisitor.cs
similarity index 64%
rename from src/ImageSharp/IImageVisitor.cs
rename to src/ImageSharp/Advanced/IImageVisitor.cs
index 971c4d37c..ba8b13e2e 100644
--- a/src/ImageSharp/IImageVisitor.cs
+++ b/src/ImageSharp/Advanced/IImageVisitor.cs
@@ -3,13 +3,13 @@
using SixLabors.ImageSharp.PixelFormats;
-namespace SixLabors.ImageSharp
+namespace SixLabors.ImageSharp.Advanced
{
///
- /// A visitor to implement double-dispatch pattern in order to apply pixel-specific operations
- /// on non-generic instances. The operation is dispatched by .
+ /// A visitor to implement a double-dispatch pattern in order to apply pixel-specific operations
+ /// on non-generic instances.
///
- internal interface IImageVisitor
+ public interface IImageVisitor
{
///
/// Provides a pixel-specific implementation for a given operation.
@@ -19,4 +19,4 @@ namespace SixLabors.ImageSharp
void Visit(Image image)
where TPixel : struct, IPixel;
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/IImage.cs b/src/ImageSharp/IImage.cs
index b9e2cee61..0d4dc3c9d 100644
--- a/src/ImageSharp/IImage.cs
+++ b/src/ImageSharp/IImage.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -11,4 +11,4 @@ namespace SixLabors.ImageSharp
public interface IImage : IImageInfo, IDisposable
{
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Image.cs b/src/ImageSharp/Image.cs
index 57f60f2e7..d7fed9016 100644
--- a/src/ImageSharp/Image.cs
+++ b/src/ImageSharp/Image.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using System;
using System.IO;
using SixLabors.ImageSharp.Advanced;
@@ -80,21 +81,11 @@ namespace SixLabors.ImageSharp
///
Configuration IConfigurable.Configuration => this.Configuration;
- ///
- /// Gets a value indicating whether the image instance is disposed.
- ///
- public bool IsDisposed { get; private set; }
-
///
public void Dispose()
{
- if (this.IsDisposed)
- {
- return;
- }
-
- this.IsDisposed = true;
- this.DisposeImpl();
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
}
///
@@ -109,8 +100,7 @@ namespace SixLabors.ImageSharp
Guard.NotNull(encoder, nameof(encoder));
this.EnsureNotDisposed();
- EncodeVisitor visitor = new EncodeVisitor(encoder, stream);
- this.AcceptVisitor(visitor);
+ this.AcceptVisitor(new EncodeVisitor(encoder, stream));
}
///
@@ -130,13 +120,6 @@ namespace SixLabors.ImageSharp
public abstract Image CloneAs(Configuration configuration)
where TPixel2 : struct, IPixel;
- ///
- /// Accept a .
- /// Implemented by invoking
- /// with the pixel type of the image.
- ///
- internal abstract void AcceptVisitor(IImageVisitor visitor);
-
///
/// Update the size of the image after mutation.
///
@@ -144,9 +127,23 @@ namespace SixLabors.ImageSharp
protected void UpdateSize(Size size) => this.size = size;
///
- /// Implements the Dispose logic.
+ /// Disposes the object and frees resources for the Garbage Collector.
+ ///
+ /// Whether to dispose of managed and unmanaged objects.
+ protected abstract void Dispose(bool disposing);
+
+ ///
+ /// Throws if the image is disposed.
+ ///
+ internal abstract void EnsureNotDisposed();
+
+ ///
+ /// Accepts a .
+ /// Implemented by invoking
+ /// with the pixel type of the image.
///
- protected abstract void DisposeImpl();
+ /// The visitor.
+ internal abstract void Accept(IImageVisitor visitor);
private class EncodeVisitor : IImageVisitor
{
diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs
index 6ea2b234c..6cdc948d4 100644
--- a/src/ImageSharp/ImageExtensions.cs
+++ b/src/ImageSharp/ImageExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -119,16 +119,5 @@ namespace SixLabors.ImageSharp
return $"data:{format.DefaultMimeType};base64,{Convert.ToBase64String(stream.ToArray())}";
}
}
-
- ///
- /// Throws if the image is disposed.
- ///
- internal static void EnsureNotDisposed(this Image image)
- {
- if (image.IsDisposed)
- {
- throw new ObjectDisposedException(nameof(image), "Trying to execute an operation on a disposed image.");
- }
- }
}
}
diff --git a/src/ImageSharp/ImageFrame.cs b/src/ImageSharp/ImageFrame.cs
index f3fe1ed8d..91872b21d 100644
--- a/src/ImageSharp/ImageFrame.cs
+++ b/src/ImageSharp/ImageFrame.cs
@@ -74,7 +74,17 @@ namespace SixLabors.ImageSharp
public Rectangle Bounds() => new Rectangle(0, 0, this.Width, this.Height);
///
- public abstract void Dispose();
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Disposes the object and frees resources for the Garbage Collector.
+ ///
+ /// Whether to dispose of managed and unmanaged objects.
+ protected abstract void Dispose(bool disposing);
internal abstract void CopyPixelsTo(Span destination)
where TDestinationPixel : struct, IPixel;
diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs
index 5c9ff489e..0436eb9d2 100644
--- a/src/ImageSharp/ImageFrame{TPixel}.cs
+++ b/src/ImageSharp/ImageFrame{TPixel}.cs
@@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp
/// In all other cases it is the only frame of the image.
///
/// The pixel format.
- public sealed class ImageFrame : ImageFrame, IPixelSource, IDisposable
+ public sealed class ImageFrame : ImageFrame, IPixelSource
where TPixel : struct, IPixel
{
private bool isDisposed;
@@ -196,20 +196,20 @@ namespace SixLabors.ImageSharp
this.UpdateSize(this.PixelBuffer.Size());
}
- ///
- /// Disposes the object and frees resources for the Garbage Collector.
- ///
- public override void Dispose()
+ ///
+ protected override void Dispose(bool disposing)
{
if (this.isDisposed)
{
return;
}
- this.PixelBuffer?.Dispose();
- this.PixelBuffer = null;
+ if (disposing)
+ {
+ this.PixelBuffer?.Dispose();
+ this.PixelBuffer = null;
+ }
- // Note disposing is done.
this.isDisposed = true;
}
diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs
index a7ea58652..3f733479d 100644
--- a/src/ImageSharp/Image{TPixel}.cs
+++ b/src/ImageSharp/Image{TPixel}.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -21,6 +21,8 @@ namespace SixLabors.ImageSharp
public sealed class Image : Image
where TPixel : struct, IPixel
{
+ private bool isDisposed;
+
///
/// Initializes a new instance of the class
/// with the height and the width of the image.
@@ -185,19 +187,41 @@ namespace SixLabors.ImageSharp
}
///
- protected override void DisposeImpl() => this.Frames.Dispose();
+ protected override void Dispose(bool disposing)
+ {
+ if (this.isDisposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ this.Frames.Dispose();
+ }
+
+ this.isDisposed = true;
+ }
+
+ ///
+ internal override void EnsureNotDisposed()
+ {
+ if (this.isDisposed)
+ {
+ throw new ObjectDisposedException("Trying to execute an operation on a disposed image.");
+ }
+ }
+
+ ///
+ public override string ToString() => $"Image<{typeof(TPixel).Name}>: {this.Width}x{this.Height}";
///
- internal override void AcceptVisitor(IImageVisitor visitor)
+ internal override void Accept(IImageVisitor visitor)
{
this.EnsureNotDisposed();
visitor.Visit(this);
}
- ///
- public override string ToString() => $"Image<{typeof(TPixel).Name}>: {this.Width}x{this.Height}";
-
///
/// Switches the buffers used by the image and the pixelSource meaning that the Image will "own" the buffer from the pixelSource and the pixelSource will now own the Images buffer.
///
diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs
index 48876251e..40b1c439e 100644
--- a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs
+++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs
@@ -25,8 +25,7 @@ namespace SixLabors.ImageSharp.Processing
Guard.NotNull(operation, nameof(operation));
source.EnsureNotDisposed();
- var visitor = new ProcessingVisitor(operation, true);
- source.AcceptVisitor(visitor);
+ source.AcceptVisitor(new ProcessingVisitor(operation, true));
}
///
@@ -42,8 +41,10 @@ namespace SixLabors.ImageSharp.Processing
Guard.NotNull(operation, nameof(operation));
source.EnsureNotDisposed();
- IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider
- .CreateImageProcessingContext(source, true);
+ IInternalImageProcessingContext operationsRunner
+ = source.GetConfiguration()
+ .ImageOperationsProvider.CreateImageProcessingContext(source, true);
+
operation(operationsRunner);
}
@@ -60,8 +61,10 @@ namespace SixLabors.ImageSharp.Processing
Guard.NotNull(operations, nameof(operations));
source.EnsureNotDisposed();
- IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider
- .CreateImageProcessingContext(source, true);
+ IInternalImageProcessingContext operationsRunner
+ = source.GetConfiguration()
+ .ImageOperationsProvider.CreateImageProcessingContext(source, true);
+
operationsRunner.ApplyProcessors(operations);
}
@@ -96,8 +99,10 @@ namespace SixLabors.ImageSharp.Processing
Guard.NotNull(operation, nameof(operation));
source.EnsureNotDisposed();
- IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider
- .CreateImageProcessingContext(source, false);
+ IInternalImageProcessingContext operationsRunner
+ = source.GetConfiguration()
+ .ImageOperationsProvider.CreateImageProcessingContext(source, false);
+
operation(operationsRunner);
return operationsRunner.GetResultImage();
}
@@ -116,8 +121,10 @@ namespace SixLabors.ImageSharp.Processing
Guard.NotNull(operations, nameof(operations));
source.EnsureNotDisposed();
- IInternalImageProcessingContext operationsRunner = source.GetConfiguration().ImageOperationsProvider
- .CreateImageProcessingContext(source, false);
+ IInternalImageProcessingContext operationsRunner
+ = source.GetConfiguration()
+ .ImageOperationsProvider.CreateImageProcessingContext(source, false);
+
operationsRunner.ApplyProcessors(operations);
return operationsRunner.GetResultImage();
}
@@ -157,8 +164,10 @@ namespace SixLabors.ImageSharp.Processing
public void Visit(Image image)
where TPixel : struct, IPixel
{
- IInternalImageProcessingContext operationsRunner = image.GetConfiguration()
- .ImageOperationsProvider.CreateImageProcessingContext(image, this.mutate);
+ IInternalImageProcessingContext operationsRunner =
+ image.GetConfiguration()
+ .ImageOperationsProvider.CreateImageProcessingContext(image, this.mutate);
+
this.operation(operationsRunner);
this.ResultImage = operationsRunner.GetResultImage();
}
diff --git a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
index 8b3e1eb96..c2c869052 100644
--- a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs
@@ -15,8 +15,6 @@ namespace SixLabors.ImageSharp.Processing.Processors
internal abstract class CloningImageProcessor : ICloningImageProcessor
where TPixel : struct, IPixel
{
- private bool isDisposed;
-
///
/// Initializes a new instance of the class.
///
@@ -104,6 +102,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public void Dispose()
{
this.Dispose(true);
+ GC.SuppressFinalize(this);
}
///
@@ -160,10 +159,6 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// Whether to dispose managed and unmanaged objects.
protected virtual void Dispose(bool disposing)
{
- if (!this.isDisposed)
- {
- this.isDisposed = true;
- }
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs
index 53eedfd20..feb4c9f19 100644
--- a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs
+++ b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
+using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
diff --git a/src/ImageSharp/Processing/Processors/ImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/ImageProcessor{TPixel}.cs
index 8ac8cd67b..55b4d3dc7 100644
--- a/src/ImageSharp/Processing/Processors/ImageProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/ImageProcessor{TPixel}.cs
@@ -15,8 +15,6 @@ namespace SixLabors.ImageSharp.Processing.Processors
internal abstract class ImageProcessor : IImageProcessor
where TPixel : struct, IPixel
{
- private bool isDisposed;
-
///
/// Initializes a new instance of the class.
///
@@ -97,6 +95,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
///
public virtual void Dispose()
{
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
}
///
@@ -142,10 +142,6 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// Whether to dispose managed and unmanaged objects.
protected virtual void Dispose(bool disposing)
{
- if (!this.isDisposed)
- {
- this.isDisposed = true;
- }
}
}
}