Harbeth 是 Apple 的 Metal 框架上的一小部分实用程序和扩展,致力于使您的 Swift GPU 代码愈加简洁,让您更快地构建管道原型。本文就来介绍与规划根据GPU的滤镜,图形处理和滤镜制造…

功用清单

现在,Metal Moudle 最重要的特点能够总结如下:

  • 支撑运算符函数式操作
  • 支撑快速规划滤镜
  • 支撑输出源的快速扩展
  • 支撑相机收集特效
  • 支撑矩阵卷积
  • 滤镜部分大致分为以下几个模块:
    • Blend:图画融合技能
    • Blur:模糊作用
    • ColorProcess:图画的基本像素色彩处理
    • Effect:作用处理
    • Lookup:查找表过滤器
    • Matrix: 矩阵卷积滤波器
    • Shape:图画形状巨细相关
    • VisualEffect: 视觉动态特效

总结下来现在共有100+种滤镜供您使用。

iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
  • 代码零侵入注入滤镜功用,
原始代码:
ImageView.image = originImage
注入滤镜代码:
let filter = C7ColorMatrix4x4(matrix: Matrix4x4.sepia)
ImageView.image = try? originImage.make(filter: filter)
  • 相机收集生成图片
注入边际检测滤镜
var filter = C7EdgeGlow()
filter.lineColor = UIColor.blue
生成相机收集器
let collector = C7FilterCollector(callback: {
    self.ImageView.image = $0
})
collector.captureSession.sessionPreset = AVCaptureSession.Preset.hd1280x720
collector.filter = filter
ImageView.layer.addSublayer(collector)

首要部分

  • 中心,基础中心板块

    • C7FilterProtocol:滤镜规划有必要遵循此协议。
      • modifier:编码器类型和对应的函数称号。
      • factors:设置修正参数因子,需求转换为Float
      • otherInputTextures:多个输入源,包含MTLTexture数组
      • outputSize:更改输出图画的巨细。
  • 输出,输出板块

    • C7FilterOutput:输出内容协议,一切输出都有必要完成该协议。
      • make:根据滤镜处理生成数据。
      • makeGroup:多个滤镜组合,请注意滤镜增加的顺序可能会影响图画生成的成果。
    • C7FilterImage:根据C7FilterOutput的图画输入源,以下形式仅支撑根据并行核算的编码器。
    • C7FilterTexture: 根据C7FilterOutput的纹路输入源,输入纹路转换成滤镜处理纹路。
    • C7CollectorCamera:相机数据收集器,直接生成图画,然后在主线程回来。
    • C7CollectorVideo:视频图画桢参加滤镜作用,直接生成图画。

规划滤镜

  • 下面我们就第一款滤镜来共享一下如何规划处理
  1. 完成协议 C7FilterProtocal
public protocol C7FilterProtocol {
     /// 编码器类型和对应的函数名
     ///
     /// 核算需求对应的`kernel`函数名
     /// 烘托需求一个`vertex`着色器函数名和一个`fragment`着色器函数名
     var modifier: Modifier { get }
     /// 制造缓冲区
     /// 设置修正参数因子,需求转换为`Float`。
     var factors: [Float] { get }
     /// 多输入源扩展
     /// 包含 `MTLTexture` 的数组
     var otherInputTextures: C7InputTextures { get }
     /// 改动输出图画的巨细
     func outputSize(input size:C7Size)-> C7Size
}
  1. 编写根据并行核算的核函数着色器。
  2. 装备传递参数因子,仅支撑Float类型。
  3. 装备额外的所需纹路。

举个例子

规划一款魂灵出窍滤镜,

iOS 利用 Metal 实现滤镜与动效滤镜

public struct C7SoulOut: C7FilterProtocol {
    /// The adjusted soul, from 0.0 to 1.0, with a default of 0.5
    public var soul: Float = 0.5
    public var maxScale: Float = 1.5
    public var maxAlpha: Float = 0.5
    public var modifier: Modifier {
        return .compute(kernel: "C7SoulOut")
    }
    public var factors: [Float] {
        return [soul, maxScale, maxAlpha]
    }
    public init() { }
}
  • 此过滤器需求三个参数:

    • soul:调整后的魂灵,从 0.0 到 1.0,默认为 0.5
    • maxScale:最大魂灵份额
    • maxAlpha:最大魂灵的透明度
  • 编写根据并行核算内核函数

kernel void C7SoulOut(texture2d<half, access::write> outputTexture [[texture(0)]],
                      texture2d<half, access::sample> inputTexture [[texture(1)]],
                      constant float *soulPointer [[buffer(0)]],
                      constant float *maxScalePointer [[buffer(1)]],
                      constant float *maxAlphaPointer [[buffer(2)]],
                      uint2 grid [[thread_position_in_grid]]) {
    constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
    const half4 inColor = inputTexture.read(grid);
    const float x = float(grid.x) / outputTexture.get_width();
    const float y = float(grid.y) / outputTexture.get_height();
    const half soul = half(*soulPointer);
    const half maxScale = half(*maxScalePointer);
    const half maxAlpha = half(*maxAlphaPointer);
    const half alpha = maxAlpha * (1.0h - soul);
    const half scale = 1.0h + (maxScale - 1.0h) * soul;
    const half soulX = 0.5h + (x - 0.5h) / scale;
    const half soulY = 0.5h + (y - 0.5h) / scale;
    const half4 soulMask = inputTexture.sample(quadSampler, float2(soulX, soulY));
    const half4 outColor = inColor * (1.0h - alpha) + soulMask * alpha;
    outputTexture.write(outColor, grid);
}
  • 简单使用,由于我这边规划的是根据并行核算管道,所以能够直接生成图片
var filter = C7SoulOut()
filter.soul = 0.5
filter.maxScale = 2.0
/// 直接显现在ImageView
ImageView.image = try? originImage.makeImage(filter: filter)
  • 至于上面的动效也很简单,增加一个计时器,然后改动soul值就完事,简单嘛。

高档用法

  • 运算符链式处理
/// 1.转换成BGRA
let filter1 = C7Color2(with: .color2BGRA)
/// 2.调整颗粒度
var filter2 = C7Granularity()
filter2.grain = 0.8
/// 3.调整白平衡
var filter3 = C7WhiteBalance()
filter3.temperature = 5555
/// 4.调整高光暗影
var filter4 = C7HighlightShadow()
filter4.shadows = 0.4
filter4.highlights = 0.5
/// 5.组合操作
let AT = C7FilterTexture.init(texture: originImage.mt.toTexture()!)
let result = AT ->> filter1 ->> filter2 ->> filter3 ->> filter4
/// 6.获取成果
filterImageView.image = result.outputImage()

iOS 利用 Metal 实现滤镜与动效滤镜

  • 批量操作处理
/// 1.转换成RBGA
let filter1 = C7Color2(with: .color2RBGA)
/// 2.调整颗粒度
var filter2 = C7Granularity()
filter2.grain = 0.8
/// 3.装备魂灵作用
var filter3 = C7SoulOut()
filter3.soul = 0.7
/// 4.组合操作
let group: [C7FilterProtocol] = [filter1, filter2, filter3]
/// 5.获取成果
filterImageView.image = try? originImage.makeGroup(filters: group)

iOS 利用 Metal 实现滤镜与动效滤镜

两种方法都能够处理多滤镜方案,怎样选择就看你心境。✌️

CocoaPods

  • 假如要导入 Metal 模块,则需求在 Podfile 中:
pod 'Harbeth'
  • 假如要导入 OpenCV 图画模块,则需求在 Podfile 中:
pod 'OpencvQueen'

作用图

  • 来一波部分展示作用图:
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜
iOS 利用 Metal 实现滤镜与动效滤镜

最终

  • 关于滤镜框架介绍与规划到此为止吧。
  • 慢慢再弥补其他相关滤镜,喜爱就给我点个星吧。
  • 滤镜Demo地址,现在包含100+种滤镜,当然也有大部分滤镜算法是参考GPUImage规划而来。
  • 再附上一个开发加快库KJCategoriesDemo地址喜爱的老板们能够点个星

✌️.