// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageSharp.Tests { using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Reflection; /// /// Extension methods for TestUtilities /// public static class TestUtilityExtensions { private static readonly Dictionary ClrTypes2PixelTypes = new Dictionary(); private static readonly Assembly ImageSharpAssembly = typeof(Color).GetTypeInfo().Assembly; private static readonly Dictionary PixelTypes2ClrTypes = new Dictionary(); private static readonly PixelTypes[] AllConcretePixelTypes = FlagsHelper .GetSortedValues() .Except(new [] {PixelTypes.Undefined, PixelTypes.All }) .ToArray(); static TestUtilityExtensions() { string nameSpace = typeof(Color).FullName; nameSpace = nameSpace.Substring(0, nameSpace.Length - typeof(Color).Name.Length - 1); foreach (PixelTypes pt in AllConcretePixelTypes.Where(pt => pt != PixelTypes.StandardImageClass)) { string typeName = $"{nameSpace}.{FlagsHelper.ToString(pt)}"; var t = ImageSharpAssembly.GetType(typeName); if (t != null) { PixelTypes2ClrTypes[pt] = t; ClrTypes2PixelTypes[t] = pt; } } PixelTypes2ClrTypes[PixelTypes.StandardImageClass] = typeof(Color); } public static Type GetPackedType(Type pixelType) { var intrfcType = pixelType.GetInterfaces() .Single(i => i.IsConstructedGenericType && i.GetGenericTypeDefinition() == typeof(IPackedPixel<>)); return intrfcType.GetGenericArguments().Single(); } public static bool HasFlag(this PixelTypes pixelTypes, PixelTypes flag) => (pixelTypes & flag) == flag; public static bool IsEquivalentTo(this Image a, Image b, bool compareAlpha = true) where TColor : struct, IPackedPixel, IEquatable { if (a.Width != b.Width || a.Height != b.Height) { return false; } byte[] bytesA = new byte[3]; byte[] bytesB = new byte[3]; using (var pixA = a.Lock()) { using (var pixB = b.Lock()) { for (int y = 0; y < a.Height; y++) { for (int x = 0; x < a.Width; x++) { var ca = pixA[x, y]; var cb = pixB[x, y]; if (compareAlpha) { if (!ca.Equals(cb)) { return false; } } else { ca.ToBytes(bytesA, 0, ComponentOrder.XYZ); cb.ToBytes(bytesB, 0, ComponentOrder.XYZ); if (bytesA[0] != bytesB[0] || bytesA[1] != bytesB[1] || bytesA[2] != bytesB[2]) { return false; } } } } } } return true; } public static string ToCsv(this IEnumerable items, string separator = ",") { return string.Join(separator, items.Select(o => string.Format(CultureInfo.InvariantCulture, "{0}", o))); } public static Type ToType(this PixelTypes pixelType) => PixelTypes2ClrTypes[pixelType]; public static PixelTypes GetPixelType(this Type colorStructClrType) => ClrTypes2PixelTypes[colorStructClrType]; public static IEnumerable> ExpandAllTypes(this PixelTypes pixelTypes) { if (pixelTypes == PixelTypes.Undefined) { return Enumerable.Empty>(); } else if (pixelTypes == PixelTypes.All) { // TODO: Need to return unknown types here without forcing CLR to load all types in ImageSharp assembly return PixelTypes2ClrTypes; } return AllConcretePixelTypes .Where(pt => pixelTypes.HasFlag(pt)) .Select(pt => new KeyValuePair(pt, pt.ToType())); } } }