diff --git a/src/ImageProcessorCore/ImageBase.cs b/src/ImageProcessorCore/ImageBase.cs index f1bf33e5c..a22ec958b 100644 --- a/src/ImageProcessorCore/ImageBase.cs +++ b/src/ImageProcessorCore/ImageBase.cs @@ -41,7 +41,7 @@ namespace ImageProcessorCore /// method will not dispose again. This help not to prolong the entity's /// life in the Garbage Collector. /// - protected bool IsDisposed; + internal bool IsDisposed; /// /// Initializes a new instance of the class. diff --git a/src/ImageProcessorCore/ImageExtensions.cs b/src/ImageProcessorCore/ImageExtensions.cs index 025c739b9..67a6f9c61 100644 --- a/src/ImageProcessorCore/ImageExtensions.cs +++ b/src/ImageProcessorCore/ImageExtensions.cs @@ -78,9 +78,7 @@ namespace ImageProcessorCore /// The . public static Image Process(this Image source, Rectangle sourceRectangle, IImageProcessor processor) { - source = PerformAction(source, true, (sourceImage, targetImage) => processor.Apply(targetImage, sourceImage, sourceRectangle)); - - return source; + return PerformAction(source, true, (sourceImage, targetImage) => processor.Apply(targetImage, sourceImage, sourceRectangle)); } /// @@ -94,7 +92,7 @@ namespace ImageProcessorCore /// The target image height. /// The processor to apply to the image. /// The . - internal static Image Process(this Image source, int width, int height, IImageSampler sampler) + public static Image Process(this Image source, int width, int height, IImageSampler sampler) { return Process(source, width, height, source.Bounds, default(Rectangle), sampler); } @@ -102,8 +100,7 @@ namespace ImageProcessorCore /// /// Applies the collection of processors to the image. /// - /// This method does will resize the target image if the source and target - /// rectangles are different. + /// This method does will resize the target image if the source and target rectangles are different. /// /// /// The source image. Cannot be null. @@ -120,9 +117,7 @@ namespace ImageProcessorCore /// The . public static Image Process(this Image source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, IImageSampler sampler) { - source = PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle)); - - return source; + return PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle)); } /// @@ -134,6 +129,11 @@ namespace ImageProcessorCore /// The . private static Image PerformAction(Image source, bool clone, Action action) { + if (source.IsDisposed) + { + throw new ObjectDisposedException("Image"); + } + Image transformedImage = clone ? new Image(source) : new Image @@ -165,9 +165,11 @@ namespace ImageProcessorCore } } - // Clean up. - source.Dispose(); - return transformedImage; + // According to http://stackoverflow.com/questions/37921815/idisposable-unmanaged-fields-reference-types-and-assignments/37922955#37922955 + // There's no need to dispose of the original image as the GC will get around to cleaning it up now there are no references to the original data. + // TODO: Investigate how log this is held onto and try to keep that to a minimum. + source = transformedImage; + return source; } } } diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs index f7f503e78..247c2bd52 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs @@ -388,6 +388,42 @@ } } + [Fact] + public void ImageShouldNotDispose() + { + if (!Directory.Exists("TestOutput/Dispose")) + { + Directory.CreateDirectory("TestOutput/Dispose"); + } + + foreach (string file in Files) + { + using (FileStream stream = File.OpenRead(file)) + { + Stopwatch watch = Stopwatch.StartNew(); + string filename = Path.GetFileName(file); + + Image image = new Image(stream); + image = image.BackgroundColor(Color.RebeccaPurple); + using (FileStream output = File.OpenWrite($"TestOutput/Dispose/{filename}")) + { + ResizeOptions options = new ResizeOptions() + { + Size = new Size(image.Width - 200, image.Height), + Mode = ResizeMode.Stretch + }; + + image.Resize(options, this.ProgressUpdate) + .Save(output); + } + + image.Dispose(); + + Trace.WriteLine($"{filename}: {watch.ElapsedMilliseconds}ms"); + } + } + } + [Theory] [MemberData("RotateFlips")] public void ImageShouldRotateFlip(RotateType rotateType, FlipType flipType)