Browse Source

ImageFrameCollection now properly implements IDisposable interface & ensures all operations are called on valid object

pull/1629/head
Dmitry Pentin 5 years ago
parent
commit
cbca565788
  1. 95
      src/ImageSharp/ImageFrameCollection.cs
  2. 3
      src/ImageSharp/ImageFrameCollection{TPixel}.cs

95
src/ImageSharp/ImageFrameCollection.cs

@ -11,8 +11,10 @@ namespace SixLabors.ImageSharp
/// Encapsulates a pixel-agnostic collection of <see cref="ImageFrame"/> instances /// Encapsulates a pixel-agnostic collection of <see cref="ImageFrame"/> instances
/// that make up an <see cref="Image"/>. /// that make up an <see cref="Image"/>.
/// </summary> /// </summary>
public abstract class ImageFrameCollection : IEnumerable<ImageFrame> public abstract class ImageFrameCollection : IDisposable, IEnumerable<ImageFrame>
{ {
private bool isDisposed;
/// <summary> /// <summary>
/// Gets the number of frames. /// Gets the number of frames.
/// </summary> /// </summary>
@ -21,7 +23,15 @@ namespace SixLabors.ImageSharp
/// <summary> /// <summary>
/// Gets the root frame. /// Gets the root frame.
/// </summary> /// </summary>
public ImageFrame RootFrame => this.NonGenericRootFrame; public ImageFrame RootFrame
{
get
{
this.EnsureNotDisposed();
return this.NonGenericRootFrame;
}
}
/// <summary> /// <summary>
/// Gets the root frame. (Implements <see cref="RootFrame"/>.) /// Gets the root frame. (Implements <see cref="RootFrame"/>.)
@ -36,7 +46,15 @@ namespace SixLabors.ImageSharp
/// </value> /// </value>
/// <param name="index">The index.</param> /// <param name="index">The index.</param>
/// <returns>The <see cref="ImageFrame"/> at the specified index.</returns> /// <returns>The <see cref="ImageFrame"/> at the specified index.</returns>
public ImageFrame this[int index] => this.NonGenericGetFrame(index); public ImageFrame this[int index]
{
get
{
this.EnsureNotDisposed();
return this.NonGenericGetFrame(index);
}
}
/// <summary> /// <summary>
/// Determines the index of a specific <paramref name="frame"/> in the <seealso cref="ImageFrameCollection"/>. /// Determines the index of a specific <paramref name="frame"/> in the <seealso cref="ImageFrameCollection"/>.
@ -59,7 +77,12 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
/// <param name="source">The raw pixel data to generate the <seealso cref="ImageFrame{TPixel}"/> from.</param> /// <param name="source">The raw pixel data to generate the <seealso cref="ImageFrame{TPixel}"/> from.</param>
/// <returns>The cloned <see cref="ImageFrame{TPixel}"/>.</returns> /// <returns>The cloned <see cref="ImageFrame{TPixel}"/>.</returns>
public ImageFrame AddFrame(ImageFrame source) => this.NonGenericAddFrame(source); public ImageFrame AddFrame(ImageFrame source)
{
this.EnsureNotDisposed();
return this.NonGenericAddFrame(source);
}
/// <summary> /// <summary>
/// Removes the frame at the specified index and frees all freeable resources associated with it. /// Removes the frame at the specified index and frees all freeable resources associated with it.
@ -91,7 +114,12 @@ namespace SixLabors.ImageSharp
/// <param name="index">The zero-based index of the frame to export.</param> /// <param name="index">The zero-based index of the frame to export.</param>
/// <exception cref="InvalidOperationException">Cannot remove last frame.</exception> /// <exception cref="InvalidOperationException">Cannot remove last frame.</exception>
/// <returns>The new <see cref="Image{TPixel}"/> with the specified frame.</returns> /// <returns>The new <see cref="Image{TPixel}"/> with the specified frame.</returns>
public Image ExportFrame(int index) => this.NonGenericExportFrame(index); public Image ExportFrame(int index)
{
this.EnsureNotDisposed();
return this.NonGenericExportFrame(index);
}
/// <summary> /// <summary>
/// Creates an <see cref="Image{T}"/> with only the frame at the specified index /// Creates an <see cref="Image{T}"/> with only the frame at the specified index
@ -99,7 +127,12 @@ namespace SixLabors.ImageSharp
/// </summary> /// </summary>
/// <param name="index">The zero-based index of the frame to clone.</param> /// <param name="index">The zero-based index of the frame to clone.</param>
/// <returns>The new <see cref="Image{TPixel}"/> with the specified frame.</returns> /// <returns>The new <see cref="Image{TPixel}"/> with the specified frame.</returns>
public Image CloneFrame(int index) => this.NonGenericCloneFrame(index); public Image CloneFrame(int index)
{
this.EnsureNotDisposed();
return this.NonGenericCloneFrame(index);
}
/// <summary> /// <summary>
/// Creates a new <seealso cref="ImageFrame{TPixel}" /> and appends it to the end of the collection. /// Creates a new <seealso cref="ImageFrame{TPixel}" /> and appends it to the end of the collection.
@ -107,7 +140,12 @@ namespace SixLabors.ImageSharp
/// <returns> /// <returns>
/// The new <see cref="ImageFrame{TPixel}" />. /// The new <see cref="ImageFrame{TPixel}" />.
/// </returns> /// </returns>
public ImageFrame CreateFrame() => this.NonGenericCreateFrame(); public ImageFrame CreateFrame()
{
this.EnsureNotDisposed();
return this.NonGenericCreateFrame();
}
/// <summary> /// <summary>
/// Creates a new <seealso cref="ImageFrame{TPixel}" /> and appends it to the end of the collection. /// Creates a new <seealso cref="ImageFrame{TPixel}" /> and appends it to the end of the collection.
@ -116,14 +154,53 @@ namespace SixLabors.ImageSharp
/// <returns> /// <returns>
/// The new <see cref="ImageFrame{TPixel}" />. /// The new <see cref="ImageFrame{TPixel}" />.
/// </returns> /// </returns>
public ImageFrame CreateFrame(Color backgroundColor) => this.NonGenericCreateFrame(backgroundColor); public ImageFrame CreateFrame(Color backgroundColor)
{
this.EnsureNotDisposed();
return this.NonGenericCreateFrame(backgroundColor);
}
/// <inheritdoc /> /// <inheritdoc />
public IEnumerator<ImageFrame> GetEnumerator() => this.NonGenericGetEnumerator(); public void Dispose()
{
if (this.isDisposed)
{
return;
}
this.DisposeManaged();
this.isDisposed = true;
}
/// <inheritdoc />
public IEnumerator<ImageFrame> GetEnumerator()
{
this.EnsureNotDisposed();
return this.NonGenericGetEnumerator();
}
/// <inheritdoc/> /// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
/// <summary>
/// Throws <see cref="ObjectDisposedException"/> if the image frame is disposed.
/// </summary>
protected void EnsureNotDisposed()
{
if(this.isDisposed)
{
throw new ObjectDisposedException("Trying to execute an operation on a disposed image frame.");
}
}
/// <summary>
/// Internal routine for freeing managed resources called from <see cref="Dispose"/>
/// </summary>
protected abstract void DisposeManaged();
/// <summary> /// <summary>
/// Implements <see cref="GetEnumerator"/>. /// Implements <see cref="GetEnumerator"/>.
/// </summary> /// </summary>

3
src/ImageSharp/ImageFrameCollection{TPixel}.cs

@ -335,7 +335,8 @@ namespace SixLabors.ImageSharp
} }
} }
internal void Dispose() /// <inheritdoc/>
protected override void DisposeManaged()
{ {
foreach (ImageFrame<TPixel> f in this.frames) foreach (ImageFrame<TPixel> f in this.frames)
{ {

Loading…
Cancel
Save