191 строка
6.2 KiB
C#
191 строка
6.2 KiB
C#
#if !__WATCHOS__
|
|
|
|
using System;
|
|
using System.Threading;
|
|
|
|
using Foundation;
|
|
using CoreImage;
|
|
using CoreGraphics;
|
|
using ObjCRuntime;
|
|
#if MONOMAC
|
|
using AppKit;
|
|
using PlatformImage = AppKit.NSImage;
|
|
#else
|
|
using UIKit;
|
|
using PlatformImage = UIKit.UIImage;
|
|
#endif
|
|
using NUnit.Framework;
|
|
using Xamarin.Utils;
|
|
|
|
namespace MonoTouchFixtures.CoreImage {
|
|
[TestFixture]
|
|
[Preserve (AllMembers = true)]
|
|
public class CIKernelTests {
|
|
// macOS: the __sample type is available starting in 10.11
|
|
const string NoOpColorKernel = @"kernel vec4 doNothing ( __sample s) { return s.rgba; }";
|
|
const string NoOpWithParamColorKernel = @"kernel vec4 doNothingWithParam ( __sample s, float d) { return s.rgba; }";
|
|
const string PositionColorKernel = @"kernel vec4 vignette ( __sample s, vec2 centerOffset, float radius )
|
|
{
|
|
vec2 vecFromCenter = destCoord () - centerOffset;
|
|
float distance = length ( vecFromCenter );
|
|
float darken = 1.0 - (distance / radius);
|
|
return vec4 (s.rgb * darken, s.a);
|
|
}";
|
|
const string NoOpWarpKernel = @"kernel vec2 doNothingWarp () { return destCoord (); }";
|
|
|
|
enum CustomerFilterType { NoOpColor, NoOpColorWithParam, ColorPositionKernel, NoOpWarpKernel };
|
|
|
|
class MyCustomFilter : CIFilter {
|
|
public MyCustomFilter (CustomerFilterType type)
|
|
{
|
|
Type = type;
|
|
kernel = CIKernel.FromProgramSingle (GetKernelString ());
|
|
Assert.IsNotNull (kernel, $"Kernel: {Type}");
|
|
}
|
|
|
|
public bool IsColorKernel {
|
|
get {
|
|
switch (Type) {
|
|
case CustomerFilterType.NoOpColor:
|
|
case CustomerFilterType.NoOpColorWithParam:
|
|
case CustomerFilterType.ColorPositionKernel:
|
|
return true;
|
|
case CustomerFilterType.NoOpWarpKernel:
|
|
return false;
|
|
}
|
|
throw new InvalidOperationException ();
|
|
}
|
|
}
|
|
|
|
string GetKernelString ()
|
|
{
|
|
switch (Type) {
|
|
case CustomerFilterType.NoOpColor:
|
|
return NoOpColorKernel;
|
|
case CustomerFilterType.NoOpColorWithParam:
|
|
return NoOpWithParamColorKernel;
|
|
case CustomerFilterType.ColorPositionKernel:
|
|
return PositionColorKernel;
|
|
case CustomerFilterType.NoOpWarpKernel:
|
|
return NoOpWarpKernel;
|
|
}
|
|
throw new InvalidOperationException ();
|
|
}
|
|
|
|
NSObject [] GetParms ()
|
|
{
|
|
switch (Type) {
|
|
case CustomerFilterType.NoOpColor:
|
|
return new NSObject [] { MyImage };
|
|
case CustomerFilterType.NoOpColorWithParam:
|
|
return new NSObject [] { MyImage, new NSNumber (5) };
|
|
case CustomerFilterType.ColorPositionKernel:
|
|
var dod = MyImage.Extent;
|
|
double radius = 0.5 * Math.Sqrt (Math.Pow (dod.Width, 2) + Math.Pow (dod.Height, 2));
|
|
CIVector centerOffset = new CIVector ((float) (dod.Size.Width * .5), (float) (dod.Size.Height * .5));
|
|
return new NSObject [] { MyImage, centerOffset, new NSNumber (radius) };
|
|
case CustomerFilterType.NoOpWarpKernel:
|
|
return new NSObject [] { };
|
|
}
|
|
throw new InvalidOperationException ();
|
|
}
|
|
|
|
CustomerFilterType Type { get; set; }
|
|
public CIImage MyImage { get; set; }
|
|
public bool CallbackHit { get; private set; }
|
|
|
|
public CIKernel kernel;
|
|
|
|
public override CIImage OutputImage {
|
|
get {
|
|
if (IsColorKernel) {
|
|
return kernel.ApplyWithExtent (MyImage.Extent, (index, rect) => {
|
|
CallbackHit = true;
|
|
return rect;
|
|
}, GetParms ());
|
|
} else {
|
|
CIWarpKernel warp = (CIWarpKernel) kernel;
|
|
return warp.ApplyWithExtent (MyImage.Extent, (index, rect) => {
|
|
CallbackHit = true;
|
|
return rect;
|
|
}, MyImage, GetParms ());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void CIKernel_BasicTest ()
|
|
{
|
|
TestRuntime.AssertSystemVersion (ApplePlatform.iOS, 8, 0, throwIfOtherPlatform: false);
|
|
TestRuntime.AssertSystemVersion (ApplePlatform.MacOSX, 10, 11, throwIfOtherPlatform: false);
|
|
|
|
Exception ex = null;
|
|
var t = new Thread (() => {
|
|
// This code will crash if an MKMapView has been created previously on
|
|
// the same thread, so just run it on a different thread (MKMapViews can
|
|
// only be created on the main thread). This is obviously an Apple bug,
|
|
// and a radar has been filed: 19249153. ObjC test case: https://github.com/rolfbjarne/CIKernelMKMapViewCrash
|
|
try {
|
|
PlatformImage uiImg = new PlatformImage (NSBundle.MainBundle.PathForResource ("Xam", "png", "CoreImage"));
|
|
#if MONOMAC
|
|
CIImage ciImg = new CIImage (uiImg.CGImage);
|
|
CIContext context = new CIContext (null);
|
|
#else
|
|
CIImage ciImg = new CIImage (uiImg);
|
|
CIContext context = CIContext.FromOptions (null);
|
|
#endif
|
|
|
|
|
|
#if NET
|
|
foreach (var type in Enum.GetValues<CustomerFilterType> ()) {
|
|
#else
|
|
foreach (CustomerFilterType type in Enum.GetValues (typeof (CustomerFilterType))) {
|
|
#endif
|
|
MyCustomFilter filter = new MyCustomFilter (type);
|
|
filter.MyImage = ciImg;
|
|
|
|
CIImage outputImage = filter.OutputImage;
|
|
|
|
CGImage cgImage = context.CreateCGImage (outputImage, outputImage.Extent);
|
|
#if MONOMAC
|
|
NSImage finalImg = new NSImage (cgImage, new CGSize ());
|
|
#else
|
|
UIImage finalImg = new UIImage (cgImage);
|
|
#endif
|
|
Assert.IsNotNull (finalImg, "CIKernel_BasicTest should not be null");
|
|
Assert.IsTrue (filter.CallbackHit, "CIKernel_BasicTest callback must be hit");
|
|
if (filter.IsColorKernel)
|
|
Assert.IsTrue (filter.kernel is CIColorKernel, "CIKernel_BasicTest we disagree that it is a color kernel");
|
|
else
|
|
Assert.IsTrue (filter.kernel is CIWarpKernel, "CIKernel_BasicTest we disagree that it is a warp kernel");
|
|
}
|
|
} catch (Exception ex2) {
|
|
ex = ex2;
|
|
}
|
|
});
|
|
t.Start ();
|
|
t.Join ();
|
|
if (ex is not null)
|
|
throw ex;
|
|
}
|
|
|
|
[Test]
|
|
public void CIKernel_TestFromPrograms ()
|
|
{
|
|
TestRuntime.AssertSystemVersion (ApplePlatform.iOS, 8, 0, throwIfOtherPlatform: false);
|
|
TestRuntime.AssertSystemVersion (ApplePlatform.MacOSX, 10, 11, throwIfOtherPlatform: false);
|
|
|
|
CIKernel [] kernels =
|
|
CIKernel.FromProgramMultiple (
|
|
NoOpColorKernel + "\n" + NoOpWithParamColorKernel + "\n" + PositionColorKernel + "\n" + NoOpWarpKernel);
|
|
Assert.AreEqual (4, kernels.Length, "CIKernel_TestFromPrograms did not get back the right number of programs");
|
|
foreach (CIKernel kernel in kernels) {
|
|
Assert.IsTrue (kernel is CIColorKernel || kernel is CIWarpKernel, "CIKernel_TestFromPrograms is neither type of kernel?");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // !__WATCHOS__
|