Browse Source

drop callbacks

test by mocking encoder
af/merge-core
Scott Williams 9 years ago
parent
commit
469d404944
  1. 19
      src/ImageSharp/Configuration.cs
  2. 46
      src/ImageSharp/Image/IImageCallbacks.cs
  3. 12
      src/ImageSharp/Image/ImageBase{TColor}.cs
  4. 5
      src/ImageSharp/Image/Image{TColor}.cs
  5. 13
      tests/ImageSharp.Tests/Drawing/Paths/ProcessorWatchingImage.cs
  6. 113
      tests/ImageSharp.Tests/Image/ImageSaveTests.cs
  7. 53
      tests/ImageSharp.Tests/Image/SaveWatchingImage.cs

19
src/ImageSharp/Configuration.cs

@ -34,6 +34,25 @@ namespace ImageSharp
/// </summary>
private readonly List<IImageFormat> imageFormatsList = new List<IImageFormat>();
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
public Configuration()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Configuration" /> class.
/// </summary>
/// <param name="providers">The inital set of image formats.</param>
public Configuration(params IImageFormat[] providers)
{
foreach (IImageFormat p in providers)
{
this.AddImageFormat(p);
}
}
/// <summary>
/// Gets the default <see cref="Configuration"/> instance.
/// </summary>

46
src/ImageSharp/Image/IImageCallbacks.cs

@ -1,46 +0,0 @@
// <copyright file="IImageCallbacks.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using ImageSharp.Processing;
/// <summary>
/// Provides a set of methods that are called as part of the images lifetime/processes.
/// </summary>
internal interface IImageCallbacks
{
/// <summary>
/// Invoked before the image is saved.
/// </summary>
/// <typeparam name="TColor">The color</typeparam>
/// <param name="image">The image</param>
/// <param name="stream">The destination stream</param>
/// <param name="encoder">The encoder</param>
/// <param name="options">The options</param>
/// <returns>
/// return true if the processor should be applied otherwise false.
/// </returns>
bool OnSaving<TColor>(ImageBase<TColor> image, Stream stream, Formats.IImageEncoder encoder, IEncoderOptions options)
where TColor : struct, IPixel<TColor>;
/// <summary>
/// Invoked before the image is processed.
/// </summary>
/// <typeparam name="TColor">The color</typeparam>
/// <param name="image">The image</param>
/// <param name="processor">The processor.</param>
/// <param name="rectangle">The rectangle.</param>
/// <returns>
/// return true if the processor should be applied otherwise false.
/// </returns>
bool OnProcessing<TColor>(ImageBase<TColor> image, IImageProcessor<TColor> processor, Rectangle rectangle)
where TColor : struct, IPixel<TColor>;
}
}

12
src/ImageSharp/Image/ImageBase{TColor}.cs

@ -116,11 +116,6 @@ namespace ImageSharp
/// </summary>
public Configuration Configuration { get; private set; }
/// <summary>
/// Gets or sets the callbacks item which will be called during the lifetime of the image being processed.
/// </summary>
internal IImageCallbacks Callbacks { get; set; }
/// <summary>
/// Applies the processor.
/// </summary>
@ -128,12 +123,7 @@ namespace ImageSharp
/// <param name="rectangle">The rectangle.</param>
public virtual void ApplyProcessor(IImageProcessor<TColor> processor, Rectangle rectangle)
{
// this will be null true or false, if its null or true then apply the processor
// thus is not false then apply the processors (allows for tests to save time and not actually run the prcessor is required)
if (this.Callbacks?.OnProcessing(this, processor, rectangle) != false)
{
processor.Apply(this, rectangle);
}
processor.Apply(this, rectangle);
}
/// <inheritdoc />

5
src/ImageSharp/Image/Image{TColor}.cs

@ -594,10 +594,7 @@ namespace ImageSharp
Guard.NotNull(stream, nameof(stream));
Guard.NotNull(encoder, nameof(encoder));
if (this.Callbacks?.OnSaving(this, stream, encoder, options) != false)
{
encoder.Encode(this, stream, options);
}
encoder.Encode(this, stream, options);
}
/// <summary>

13
tests/ImageSharp.Tests/Drawing/Paths/ProcessorWatchingImage.cs

@ -12,29 +12,22 @@ namespace ImageSharp.Tests.Drawing.Paths
/// Watches but does not actually run the processors against the image.
/// </summary>
/// <seealso cref="ImageSharp.Image{ImageSharp.Color}" />
public class ProcessorWatchingImage : Image<Color>, IImageCallbacks
public class ProcessorWatchingImage : Image<Color>
{
public List<ProcessorDetails> ProcessorApplications { get; } = new List<ProcessorDetails>();
public ProcessorWatchingImage(int width, int height)
: base(width, height, Configuration.CreateDefaultInstance())
{
this.Callbacks = this;
}
public bool OnSaving<TColor>(ImageBase<TColor> image, Stream stream, IImageEncoder encoder, IEncoderOptions options) where TColor : struct, IPixel<TColor>
{
return true;
}
public bool OnProcessing<TColor>(ImageBase<TColor> image, IImageProcessor<TColor> processor, Rectangle rectangle) where TColor : struct, IPixel<TColor>
public override void ApplyProcessor(IImageProcessor<Color> processor, Rectangle rectangle)
{
this.ProcessorApplications.Add(new ProcessorDetails
{
processor = (IImageProcessor<Color>)processor,
processor = processor,
rectangle = rectangle
});
return false;// do not really apply the processor to speed up testing
}
public struct ProcessorDetails

113
tests/ImageSharp.Tests/Image/ImageSaveTests.cs

@ -18,15 +18,38 @@ namespace ImageSharp.Tests
/// </summary>
public class ImageSaveTests : IDisposable
{
private readonly SaveWatchingImage Image;
private readonly Image Image;
private readonly Mock<IFileSystem> fileSystem;
private readonly Mock<IImageFormat> format;
private readonly Mock<IImageFormat> formatNotRegistered;
private readonly Mock<IImageEncoder> encoder;
private readonly Mock<IImageEncoder> encoderNotInFormat;
private readonly IEncoderOptions encoderOptions;
public ImageSaveTests()
{
this.encoder = new Mock<IImageEncoder>();
this.format = new Mock<IImageFormat>();
this.format.Setup(x => x.Encoder).Returns(this.encoder.Object);
this.format.Setup(x => x.Decoder).Returns(new Mock<IImageDecoder>().Object);
this.format.Setup(x => x.MimeType).Returns("img/test");
this.format.Setup(x => x.Extension).Returns("png");
this.format.Setup(x => x.SupportedExtensions).Returns(new string[] { "png", "jpg" });
this.encoderNotInFormat = new Mock<IImageEncoder>();
this.formatNotRegistered = new Mock<IImageFormat>();
this.formatNotRegistered.Setup(x => x.Encoder).Returns(this.encoderNotInFormat.Object);
this.formatNotRegistered.Setup(x => x.Decoder).Returns(new Mock<IImageDecoder>().Object);
this.formatNotRegistered.Setup(x => x.MimeType).Returns("img/test");
this.formatNotRegistered.Setup(x => x.Extension).Returns("png");
this.formatNotRegistered.Setup(x => x.SupportedExtensions).Returns(new string[] { "png", "jpg" });
this.fileSystem = new Mock<IFileSystem>();
this.encoderOptions = new Mock<IEncoderOptions>().Object;
this.Image = new SaveWatchingImage(1, 1, this.fileSystem.Object);
this.Image = new Image(1, 1, new Configuration(this.format.Object) {
FileSystem = this.fileSystem.Object
});
}
[Fact]
@ -36,10 +59,7 @@ namespace ImageSharp.Tests
this.fileSystem.Setup(x => x.Create("path.png")).Returns(stream);
this.Image.Save("path.png");
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<PngEncoder>(operation.encoder);
Assert.Null(operation.options);
this.encoder.Verify(x => x.Encode<Color>(this.Image, stream, null));
}
[Fact]
@ -49,11 +69,8 @@ namespace ImageSharp.Tests
this.fileSystem.Setup(x => x.Create("path.jpg")).Returns(stream);
this.Image.Save("path.jpg", this.encoderOptions);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<JpegEncoder>(operation.encoder);
Assert.Equal(this.encoderOptions, operation.options);
this.encoder.Verify(x => x.Encode<Color>(this.Image, stream, this.encoderOptions));
}
[Fact]
@ -62,12 +79,9 @@ namespace ImageSharp.Tests
Stream stream = new MemoryStream();
this.fileSystem.Setup(x => x.Create("path.jpg")).Returns(stream);
this.Image.Save("path.jpg", new BmpEncoder());
this.Image.Save("path.jpg", this.encoderNotInFormat.Object);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<BmpEncoder>(operation.encoder);
Assert.Null(operation.options);
this.encoderNotInFormat.Verify(x => x.Encode<Color>(this.Image, stream, null));
}
[Fact]
@ -76,12 +90,9 @@ namespace ImageSharp.Tests
Stream stream = new MemoryStream();
this.fileSystem.Setup(x => x.Create("path.jpg")).Returns(stream);
this.Image.Save("path.jpg", new BmpEncoder(), this.encoderOptions);
this.Image.Save("path.jpg", this.encoderNotInFormat.Object, this.encoderOptions);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<BmpEncoder>(operation.encoder);
Assert.Equal(this.encoderOptions, operation.options);
this.encoderNotInFormat.Verify(x => x.Encode<Color>(this.Image, stream, this.encoderOptions));
}
@ -92,12 +103,9 @@ namespace ImageSharp.Tests
Stream stream = new MemoryStream();
this.fileSystem.Setup(x => x.Create("path.jpg")).Returns(stream);
this.Image.Save("path.jpg", new GifFormat());
this.Image.Save("path.jpg", this.encoderNotInFormat.Object);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<GifEncoder>(operation.encoder);
Assert.Null(operation.options);
this.encoderNotInFormat.Verify(x => x.Encode<Color>(this.Image, stream, null));
}
[Fact]
@ -106,29 +114,18 @@ namespace ImageSharp.Tests
Stream stream = new MemoryStream();
this.fileSystem.Setup(x => x.Create("path.jpg")).Returns(stream);
this.Image.Save("path.jpg", new BmpFormat(), this.encoderOptions);
this.Image.Save("path.jpg", this.encoderNotInFormat.Object, this.encoderOptions);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<BmpEncoder>(operation.encoder);
Assert.Equal(this.encoderOptions, operation.options);
this.encoderNotInFormat.Verify(x => x.Encode<Color>(this.Image, stream, this.encoderOptions));
}
/// <summary>
/// /////////////////////////////////////////////////////////////
/// </summary>
///
[Fact]
public void SaveStream()
{
Stream stream = new MemoryStream();
this.Image.Save(stream);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType(this.Image.CurrentImageFormat.Encoder.GetType(), operation.encoder);
Assert.Null(operation.options);
this.encoder.Verify(x => x.Encode<Color>(this.Image, stream, null));
}
[Fact]
@ -138,11 +135,7 @@ namespace ImageSharp.Tests
this.Image.Save(stream, this.encoderOptions);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType(this.Image.CurrentImageFormat.Encoder.GetType(), operation.encoder);
Assert.Equal(this.encoderOptions, operation.options);
this.encoder.Verify(x => x.Encode<Color>(this.Image, stream, this.encoderOptions));
}
[Fact]
@ -150,12 +143,9 @@ namespace ImageSharp.Tests
{
Stream stream = new MemoryStream();
this.Image.Save(stream, new BmpEncoder());
this.Image.Save(stream, this.encoderNotInFormat.Object);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<BmpEncoder>(operation.encoder);
Assert.Null(operation.options);
this.encoderNotInFormat.Verify(x => x.Encode<Color>(this.Image, stream, null));
}
[Fact]
@ -163,12 +153,9 @@ namespace ImageSharp.Tests
{
Stream stream = new MemoryStream();
this.Image.Save(stream, new BmpEncoder(), this.encoderOptions);
this.Image.Save(stream, this.encoderNotInFormat.Object, this.encoderOptions);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<BmpEncoder>(operation.encoder);
Assert.Equal(this.encoderOptions, operation.options);
this.encoderNotInFormat.Verify(x => x.Encode<Color>(this.Image, stream, this.encoderOptions));
}
[Fact]
@ -176,12 +163,9 @@ namespace ImageSharp.Tests
{
Stream stream = new MemoryStream();
this.Image.Save(stream, new GifFormat());
this.Image.Save(stream, this.formatNotRegistered.Object);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<GifEncoder>(operation.encoder);
Assert.Null(operation.options);
this.encoderNotInFormat.Verify(x => x.Encode<Color>(this.Image, stream, null));
}
[Fact]
@ -189,12 +173,9 @@ namespace ImageSharp.Tests
{
Stream stream = new MemoryStream();
this.Image.Save(stream, new BmpFormat(), this.encoderOptions);
this.Image.Save(stream, this.formatNotRegistered.Object, this.encoderOptions);
SaveWatchingImage.OperationDetails operation = this.Image.Saves.Single();
Assert.Equal(stream, operation.stream);
Assert.IsType<BmpEncoder>(operation.encoder);
Assert.Equal(this.encoderOptions, operation.options);
this.encoderNotInFormat.Verify(x => x.Encode<Color>(this.Image, stream, this.encoderOptions));
}
public void Dispose()

53
tests/ImageSharp.Tests/Image/SaveWatchingImage.cs

@ -1,53 +0,0 @@

namespace ImageSharp.Tests
{
using System;
using System.IO;
using ImageSharp;
using Processing;
using System.Collections.Generic;
using ImageSharp.Formats;
using ImageSharp.IO;
/// <summary>
/// Watches but does not actually run the processors against the image.
/// </summary>
/// <seealso cref="ImageSharp.Image{ImageSharp.Color}" />
public class SaveWatchingImage : Image<Color>, IImageCallbacks
{
public List<OperationDetails> Saves { get; } = new List<OperationDetails>();
public SaveWatchingImage(int width, int height, IFileSystem fs = null)
: base(width, height, Configuration.CreateDefaultInstance())
{
//switch out the file system for tests
this.Configuration.FileSystem = fs ?? this.Configuration.FileSystem;
this.Callbacks = this;
}
public bool OnSaving<TColor>(ImageBase<TColor> image, Stream stream, IImageEncoder encoder, IEncoderOptions options) where TColor : struct, IPixel<TColor>
{
this.Saves.Add(new OperationDetails
{
encoder = encoder,
options = options,
stream = stream
});
return false;
}
public bool OnProcessing<TColor>(ImageBase<TColor> image, IImageProcessor<TColor> processor, Rectangle rectangle) where TColor : struct, IPixel<TColor>
{
return false;
}
public struct OperationDetails
{
public Stream stream;
public IImageEncoder encoder;
public IEncoderOptions options;
}
}
}
Loading…
Cancel
Save