一、布景

你是否从前想要给你的相片增加一些特殊作用,让它们愈加引人注目?或许你是否对那些充溢艺术感的滤镜相片羡慕不已,但却以为它们需求专业的图画处理技巧?今日,我将向你提醒一个令人惊奇的事实——图片加滤镜竟如此简略!

滤镜是一种强大而又简略的工具,它能够改变图片的色彩、亮度、对比度和纹路等特性,让你的相片锋芒毕露。

在本文中,我将向你展现怎么简略运用滤镜特点为你的图片增加味道。让我们一同揭开图片加滤镜的奥秘面纱,开掘那些隐藏在简略代码背后的冷艳作用。让你的相片勃发重生,让你的创造力在滤镜的法力下绽放!让我们开始吧!

了解ios的朋友,如果说到滤镜,那么第一时间就会想到 GPUImage, 的确很好用,不过这个库已经太久不更新维护。

于是乎我这边根据Swift + Metal制造一款全新的滤镜库,这边在编写的时候,当然也有借鉴GPUImage许多滤镜算法,再次感谢大神!!!

  • 先贴链接地址:github.com/yangKJ/Harb…
Animated Still Mix
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享

话不多说,先简略介绍滤镜库 Harbeth 支撑功用:

  • 支撑ios体系和macOS体系;
  • 支撑运算符函数式操作;
  • 支撑多种形式数据源 UIImage, CIImage, CGImage, CMSampleBuffer, CVPixelBuffer
  • 支撑运用体系 MetalPerformanceShaders 滤镜和兼容 CoreImage 滤镜;
  • 支撑快速规划滤镜;
  • 支撑兼并多种滤镜作用;
  • 支撑输出源的快速扩展;
  • 支撑相机采集特效 和 视频增加滤镜特效;
  • 支撑已有视频增加滤镜并导出;

大致计算下来,这边目前也已经拥有超150多种内置滤镜供给运用,而且这边也支撑兼容体系CoreImage,这样一算那滤镜就太多了!


实现计划

该库首要分为以下几个板块,根底模块、Metal内核滤镜模块、CoreImage滤镜模块、视频滤镜模块

根底模块又首要分为以下部分:

  • Core: 该模块首要处理装备Metal信息,和CoreImage兼容转化;
  • Extensions: 该模块首要处理各类型资源和MTLTexture互相转化办法;
  • Matrix: 该模块首要包括矩阵相关,常用矩阵卷积内核和常用色彩矩阵;
  • Outputs: 该模块首要包括对外转化,BoxxIO快速向源增加过滤器;
  • Setup: 该模块首要包括装备信息,该库运用的小工具等;

怎么运用

  • 代码彻底能够做到零侵入对图画注入滤镜功用,然后显现在UIImageView控件;
 - 原始代码:
lazy var ImageView: UIImageView = {
  let imageView = UIImageView(image: originImage)
  imageView.layer.borderColor = R.color("background2")?.cgColor
  imageView.layer.borderWidth = 0.5
  return imageView
}()
ImageView.image = originImage

图画增加滤镜

 - 注入滤镜代码:
let filter1 = C7ColorMatrix4x4(matrix: Matrix4x4.Color.sepia)
let filter2 = C7Granularity(grain: 0.8)
let filter3 = C7SoulOut(soul: 0.7)
let filters = [filter1, filter2, filter3]
简略运用`Outputable`  
ImageView.image = try? originImage.makeGroup(filters: filters)

指定图画数据源

  • 能够高性能在这些数据源快速增加过滤器,例如:NSImage、UIImage、CIImage、CGImage、CMSampleBuffer, CVPixelBuffer;
  • 其间CMSampleBuffer首要为相机采集回来的缓冲数据,CVPixelBuffer则能够简略用于播映视频增加滤镜;
也可数据源形式运用
let dest = BoxxIO.init(element: originImage, filters: filters)
// 同步处理
ImageView.image = try? dest.output()

异步处理

// 异步处理
dest.transmitOutput(success: { [weak self] image in
    DispatchQueue.main.async {
        self?.ImageView.image = image
    }
})

运算符

或许运算符操作
ImageView.image = originImage -->>> filters
甚至不定参数运用
ImageView.image = originImage.filtering(filter, filter2, filter3)

总之这么多种计划,怎么运用就看你的心情了!!!

怎么规划滤镜

这边彻底选用协议方法,用于自定义各种滤镜;

滤镜类型

  • 首要包括以下几种类型滤镜;
public enum Modifier {
    /// 根据`MTLComputeCommandEncoder`并行计算编码器,可直接生成图片
    case compute(kernel: String)
    /// 根据`MTLRenderCommandEncoder`烘托 3D 编码器,需配合`MTKView`方能显现
    case render(vertex: String, fragment: String)
    /// 根据`MTLBlitCommandEncoder`位图复制编码器,拷贝纹路一起也能生成贴图
    case blit
    /// 根据`CoreImage`,直接生成图片
    case coreimage(CIName: String)
    /// 根据`MetalPerformanceShaders`着色器
    case mps(performance: MPSUnaryImageKernel)
}

首要包括下面几个协议,

  • C7FilterPorotocal: 根底协议,包括滤镜类型Modifier、参数因子、其他输入源、以及修正尺度巨细;
  • ComputeFiltering: 该协议首要用于根据内核形式,传递特殊参数因子;
  • CoreImageFiltering: 该协议首要用于根据CoreImage,兼容运用体系CoreImage滤镜;
  • RenderFiltering: 该协议首要作用于根据片元着色器和顶点着色器;

根底 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. 遵从协议 C7FilterProtocal
  2. 装备额外的所需纹路
  3. 装备传递参数因子,仅支撑Float类型
  4. 编写根据并行计算的核函数着色器
  5. 简略运用,由于我这边规划的是根据并行计算管道,所以能够直接生成图片

根据内核形式的查找滤镜

kernel void C7LookupTable(texture2d<half, access::write> outputTexture [[texture(0)]],
                          texture2d<half, access::read> inputTexture [[texture(1)]],
                          texture2d<half, access::sample> lookupTexture [[texture(2)]],
                          constant float *intensity [[buffer(0)]],
                          uint2 grid [[thread_position_in_grid]]) {
    const half4 inColor = inputTexture.read(grid);
    const half blueColor = inColor.b * 63.0h; // 蓝色部分[0, 63] 共64种
    half2 quad1;
    quad1.y = floor(floor(blueColor) / 8.0h);
    quad1.x = floor(blueColor) - (quad1.y * 8.0h);
    half2 quad2;
    quad2.y = floor(ceil(blueColor) / 8.0h);
    quad2.x = ceil(blueColor) - (quad2.y * 8.0h);
    const float A = 0.125;
    const float B = 0.5 / 512.0;
    const float C = 0.125 - 1.0 / 512.0;
    float2 texPos1; // 计算色彩(r,b,g)在第一个正方形中对应位置
    texPos1.x = A * quad1.x + B + C * inColor.r;
    texPos1.y = A * quad1.y + B + C * inColor.g;
    float2 texPos2;
    texPos2.x = A * quad2.x + B + C * inColor.r;
    texPos2.y = A * quad2.y + B + C * inColor.g;
    constexpr sampler quadSampler(mag_filter::linear, min_filter::linear);
    const half4 newColor1 = lookupTexture.sample(quadSampler, texPos1);
    const half4 newColor2 = lookupTexture.sample(quadSampler, texPos2);
    const half4 newColor = mix(newColor1, newColor2, fract(blueColor));
    const half4 outColor = half4(mix(inColor, half4(newColor.rgb, inColor.a), half(*intensity)));
    outputTexture.write(outColor, grid);
}

展现图

  • 给部分作用展现
色相交融 透明度交融 亮度交融
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享
iOS 轻量化图像滤镜和视频滤镜库分享

总结

本文对于怎么运用Harbth滤镜库做了简略介绍,和怎么规划滤镜等等;
欢迎我们来运用该结构,然后指正修正亦或许我们有什么需求也可提出来,后续渐渐补充完善;
也欢迎大神来帮助运用优化此库,再次感谢!!!


对于怎么运用和规划原理先简略介绍出来,关于后续功用和优化再渐渐介绍!

觉得有帮助的铁子,就给我点个星支撑一哈,谢谢铁子们~
本文滤镜结构传送门 Harbeth 地址。
有什么问题也能够直接联络我,邮箱 yangkj310@gmail.com