下面是试图复制所述过滤器的内核的金属源代码:
#include
#include
using namespace metal;
extern "C" {
namespace coreimage {
float4 sketch(sampler src, float texelWidth, float texelHeight, float intensity40) {
float size = 1.25f + (intensity40 / 100.0f) * 2.0f;
float minVal = 1.0f;
float maxVal = 0.0f;
for (float x = -size; x < size; ++x) {
for (float y = -size; y < size; ++y) {
float4 color = src.sample(src.coord() + float2(x * texelWidth, y * texelHeight));
float val = (color.r + color.g + color.b) / 3.0f;
if (val > maxVal) {
maxVal = val;
} else if (val < minVal) {
minVal = val;
}
}
}
float range = 5.0f * (maxVal - minVal);
float4 outColor(pow(1.0f - range, size * 1.5f));
outColor = float4((outColor.r + outColor.g + outColor.b) / 3.0f > 0.75f ? float3(1.0f) : outColor.rgb, 1.0f);
return outColor;
}
}
}
我想你已经熟悉了
basics
如何正确地将金属材质球构建到可由核心图像加载的库中。
您可以在运行时通过加载默认的金属库并请求“sketch”函数来实例化内核(名称是任意的,只要它与内核源代码匹配):
NSURL *libraryURL = [NSBundle.mainBundle URLForResource:@"default" withExtension:@"metallib"];
NSData *libraryData = [NSData dataWithContentsOfURL:libraryURL];
NSError *error;
CIKernel *kernel = [CIKernel kernelWithFunctionName:@"sketch" fromMetalLibraryData:libraryData error:&error];
然后,您可以将这个内核包装在自己的映像中,从而将它应用到映像中。
CIFilter
子类,或者直接调用它:
CIImage *outputImage = [kernel applyWithExtent:CGRectMake(0, 0, width, height)
roiCallback:^CGRect(int index, CGRect destRect)
{ return destRect; }
arguments:@[inputImage, @(1.0f/width), @(1.0f/height), @(60.0f)]];
我尝试为每个参数选择合理的默认值(第一个参数应该是
CIImage
当然,这些可以根据口味调整。