1. 简介
GPUImage 是一个开源的处理图片、实时视频流、视频文件的第三方库,同时支持 Mac OS 和 iOS ,最低支持 iOS 4.0, 接口封装简单易用,里面内置了大量的滤镜供我们使用,当然也支持自定义滤镜,以及多种滤镜组合使用来完成对应的需求,目前共有 3 个版本:
- 基于
OpenGL ES的使用Objective-C封装的第一版:GPUImage - 基于
OpenGL ES的使用Swift封装的第二版: GPUImage2 - 基于
Metal的使用Swift封装的第三版:GPUImage3
2. 特点
-
源代码开源,实现透明,可定制化程度比较高。
-
丰富的输入组件
- 静态图片
- 相机拍摄的照片
- 视频(实时视频流和视频文件)
- OpenGL 纹理
- 二进制数据
- UIElement(UIView,CALayer)
-
大量的内置滤镜
- 颜色处理类,31 个滤镜(亮度、色度、饱和度、对比度...)
- 图像处理类,40 个滤镜(放射变换、裁剪、高斯模糊、毛玻璃效果...)
- 颜色混合类,29 个滤镜(差异混合、透明度混合、遮罩混合...)
- 视觉效果类,25 个滤镜(像素化、素描、浮雕、鱼眼...)
-
丰富的输出组件
- UIView
- 视频文件
- 纹理
- 二进制数据
-
灵活的滤镜链,滤镜效果之间可以互相串联、关联
-
接口简单易用,把滤镜和
OpenGL其他资源(context,program、frameBuffer)都做了统一的封装,并且内置了一个cache模块实现了frameBuffer的复用。 -
线程安全,
GPUImage创建了专门的contextQueue,所有的滤镜都会在这个队列里处理。 -
轻松实现自定义滤镜效果,无需关注
OpenGL上下文环境的搭建以及渲染流程,专注于实现核心效果算法即可。
3. 滤镜处理流程
3.1 滤镜起点
-
GPUImagePicture
处理静态图片,先解压图片,拿到解压后的位图,然后加载纹理,最后使用着色器程序对纹理进行处理。
-
GPUImageRawDataInput
拿到二进制数据使用
CoreGraphics绘制位图,然后加载纹理,最后使用着色器程序对纹理进行处理。 -
GPUImageTextureInput
直接使用着色器程序对纹理进行处理。
-
GPUImageUIElement
不管是 UIView 还是 CALayer,最终都会使用都会调用
[layer renderInContext:imageContext]方法,绘制成位图,然后加载纹理,最后使用着色器程序对纹理进行处理。 -
GPUImageMovie
拿到视频文件,使用 AVAssertReader 逐帧读取视频,将每一帧画面转为纹理,最后使用着色器程序对纹理进行处理。
-
GPUImageVideoCamera
借助
AVFoundation录制视频,在代理方法-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection拿到CMSampleBufferRef,调用CMSampleBufferGetImageBuffer获取CVImageBufferRef,然后将其转为纹理,最后使用着色器程序对纹理进行处理。 -
GPUImageStillCamera
GPUImageStillCamera继承自GPUImageVideoCamera, 处理流程和GPUImageVideoCamera一样。
3.2 滤镜终点
-
GPUImageMovieWriter
使用
AVAssetWriter把录制的视频写入指定的文件中。 -
GPUImageRawDataOutput
从帧缓冲区
framebuffer获取CVPixelBufferRef数据,然后调用CVPixelBufferGetBaseAddress(renderTarget)得到二进制数据GLubyte。 -
GPUImageTextureOutput
直接输出纹理,这个在使用滤镜链的时候用到。
-
GPUImageView
GPUImageView继承自UIView,但是他的layerClass为CAEAGLLayer,借助于OpenGL的context和CAEAGLLayer,将内容输出显示出来。
4. 核心类分析
4.1 GPUImageContext
GPUImageContext是GPUImage对OpenGL ES上下文的封装,添加了GPUImage相关的上下文,比如说Program的使用缓存,处理队列,CV纹理缓存等。
4.2 GLProgram
GLProgram是GPUImage对OpenGL ES的 program 封装,根据顶点、片元着色器源文件或者字符串生成对应的着色器程序,编译一下,然后 attach 到 program 上面,然后 link program,成功以后就可以 user program 了。创建了针对 attribute 和 uniform 的数据创建了对应的数组,方便在使用滤镜的时候进行数据绑定。
4.3 GPUImageFramebuffer
GPUImageFramebuffer是GPUImage对OpenGL ES的 frameBuffer 封装,负责处理帧缓冲区里面的操作,生成顶点坐标数据,将顶点数据从 CPU 拷贝到 GPU 的显存中,并且生成纹理,设置纹理的放大缩小过滤方式(GL_TEXTURE_MIN_FILTER,GL_TEXTURE_MAG_FILTER)以及环绕方式(GL_TEXTURE_WRAP_S,GL_TEXTURE_WRAP_T),如果使用 mipmap,还需要处理 mipmap 相关设置。默认不使用 mipmap。
4.4 GPUImageFramebufferCache
GPUImageFramebufferCache是GPUImageFrameBuffer的管理类,使用 NSMutableDictionary 缓存 GPUImageFrameBuffer,并且在收到内存警告的时候清空缓存。
5. 不足之处
- 不支持人脸检测,二维码条形码识别,iOS 系统的 CoreImage 是支持人脸检测的。
- 对应大图的处理会导致图像质量损失,GPUImage 在纹理大小超过 4096 * 4096 的时候,会自动压缩成支持的最大尺寸纹理的图像,然后再进行进一步处理。