//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
namespace ImageSharp.Tests
{
using System;
using System.Collections.Concurrent;
using System.Reflection;
///
/// Provides instances for parametric unit tests.
///
/// The pixel format of the image
public abstract class TestImageProvider : ITestImageFactory
where TColor : struct, IPackedPixel, IEquatable
{
public PixelTypes PixelType { get; private set; } = typeof(TColor).GetPixelType();
public virtual string SourceFileOrDescription => "";
///
/// Utility instance to provide informations about the test image & manage input/output
///
public ImagingTestCaseUtility Utility { get; private set; }
public GenericFactory Factory { get; private set; } = new GenericFactory();
public static TestImageProvider Blank(
int width,
int height,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
=> new BlankProvider(width, height).Init(testMethod, pixelTypeOverride);
public static TestImageProvider File(
string filePath,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
{
return new FileProvider(filePath).Init(testMethod, pixelTypeOverride);
}
public static TestImageProvider Lambda(
Func, Image> func,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
=> new LambdaProvider(func).Init(testMethod, pixelTypeOverride);
public static TestImageProvider Solid(
int width,
int height,
byte r,
byte g,
byte b,
byte a = 255,
MethodInfo testMethod = null,
PixelTypes pixelTypeOverride = PixelTypes.Undefined)
{
return new SolidProvider(width, height, r, g, b, a).Init(testMethod, pixelTypeOverride);
}
///
/// Returns an instance to the test case with the necessary traits.
///
public abstract Image GetImage();
protected TestImageProvider Init(MethodInfo testMethod, PixelTypes pixelTypeOverride)
{
if (pixelTypeOverride != PixelTypes.Undefined)
{
this.PixelType = pixelTypeOverride;
}
if (pixelTypeOverride == PixelTypes.StandardImageClass)
{
this.Factory = new DefaultImageClassSpecificFactory() as GenericFactory;
}
this.Utility = new ImagingTestCaseUtility()
{
SourceFileOrDescription = this.SourceFileOrDescription,
PixelTypeName = typeof(TColor).Name
};
if (testMethod != null)
{
this.Utility.Init(testMethod);
}
return this;
}
private class BlankProvider : TestImageProvider
{
public BlankProvider(int width, int height)
{
this.Width = width;
this.Height = height;
}
public override string SourceFileOrDescription => $"Blank{this.Width}x{this.Height}";
protected int Height { get; }
protected int Width { get; }
public override Image GetImage() => this.Factory.CreateImage(this.Width, this.Height);
}
private class FileProvider : TestImageProvider
{
private static ConcurrentDictionary> cache =
new ConcurrentDictionary>();
private string filePath;
public FileProvider(string filePath)
{
this.filePath = filePath;
}
public override string SourceFileOrDescription => this.filePath;
public override Image GetImage()
{
var cachedImage = cache.GetOrAdd(
this.filePath,
fn =>
{
var testFile = TestFile.Create(this.filePath);
return this.Factory.CreateImage(testFile.Bytes);
});
return new Image(cachedImage);
}
}
private class LambdaProvider : TestImageProvider
{
private readonly Func, Image> creator;
public LambdaProvider(Func, Image> creator)
{
this.creator = creator;
}
public override Image GetImage() => this.creator(this.Factory);
}
private class SolidProvider : BlankProvider
{
private readonly byte a;
private readonly byte b;
private readonly byte g;
private readonly byte r;
public SolidProvider(int width, int height, byte r, byte g, byte b, byte a)
: base(width, height)
{
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
public override string SourceFileOrDescription
=> $"Solid{this.Width}x{this.Height}_({this.r},{this.g},{this.b},{this.a})";
public override Image GetImage()
{
var image = base.GetImage();
TColor color = default(TColor);
color.PackFromBytes(this.r, this.g, this.b, this.a);
return image.Fill(color);
}
}
}
///
/// Marker
///
public interface ITestImageFactory
{
}
}