GPUImage 是一个基于 GPU 图像和视频处理的开源 iOS 框架。因为使用 GPU 来处理图像和视频,因此速度很是快,它的做者 BradLarson 称在 iPhone4 上其处理速度是使用 CPU 来处理的 100 倍 (CoreImage 也能使用 GPU 来处理图像,但我以为 CoreImage 仍是慢)。除了速度上的优点,GPUImage 还提供了不少很棒的图像处理滤镜,但有时候这些基本功能仍然没法知足实际开发中的需求,不用担忧 GPUImage 支持自定义滤镜。html
GPUImage 自定义滤镜须要使用 OpenGL 着色语言( GLSL )编写 Fragment Shader(片断着色器),除此以外你可能还须要一点点图像处理相关的知识。下面我将尝试经过 GPUImage 中的 GPUImageColorInvertFilter(反色滤镜)来说解一下它的运做过程。git
先看.h 文件:github
#import "GPUImageFilter.h" @interface GPUImageColorInvertFilter : GPUImageFilter { } @end
很简单,能够看出 GPUImageColorInvertFilter 是继承了 GPUImageFilter算法
而后看 .m 文件 中 @implementation 以前的一段代码框架
NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING ( varying highp vec2 textureCoordinate; uniform sampler2D inputImageTexture; void main() { lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.a); } );
第 1 行,能够看到 SHADER_STRING
宏中包含着咱们的 Shader (着色器)代码,咱们的着色器字符串赋给一个 const NSString 对象(这个常量将在 GPUImageFilter 及其子类的初始化过程当中用来设置 filter)。函数
第 二、3 行声明了两个变量。ui
varying
变量是Vertex 和 Fragment Shader(顶点着色器和片断着色器)之间作数据传递用的,通常 Vertex Shader(顶点着色器) 修改 varying 变量的值,而后 Fragment Shader(片断着色器)使用该varying变量的值。所以varying 变量在 Vertex 和 Fragment Shader 中声明必须一致。放到这里,也就是说 textureCoordinate
必须叫这个名字不能改。3d
highp
声明 textureCoordinate
精度(相应的还有mediump
和lowp
)。code
vec2
声明textureCoordinate
是一个二维向量。orm
uniform
声明 inputImageTexture
是外部程序传递给 Shader 的变量, Shader 程序内部只能用,不能改。 sampler2D
声明变量是一个2D纹理。
第 4 行,相信你并不陌生,没错儿 Shader 也是从 main() 函数开始执行的。
第 5 行,texture2D
纹理取样器,根据纹理坐标返回纹理单元的值。
第 6 行,(1.0 - textureColor.rgb)
去 textureColor
也就是原图的 RGB 值,作了一个向量的减法,这是图像的反色算法,而后把通过反色的 RGB 值和原图的 Alpha 值组成一个新的 vec4(四维向量)值赋给 gl_FragColor
。 gl_FragColor
是 Fragment Shader 预先定义的变量,赋给它的值就是该片断最终的颜色值。
Shader 到这里已经解释完了,可能你依然云里雾里,我来讲一下我对这部分功能的理解,可能不对,但目前是管用的,方便你理解:GPUImage 中应该有一个 Vertex Shader,它对图像逐个像素扫描,经过 textureCoordinate
变量将当前的扫描坐标传递给咱们的 Fragment Shader,inputImageTexture
包含咱们要处理的图像的所有信息,在 Shader 程序内部经过 texture2D
获得 inputImageTexture
在当前位置 textureCoordinate
的 RGBA 值,运用图像处理知识,算出想要的新的 RGBA 值,把结果值赋给 gl_FragColor
就算完成了。
如今咱们继续看代码,在 Shader 以后是 GPUImageColorInvertFilter 的实现:
@implementation GPUImageColorInvertFilter - (id)init; { if (!(self = [super initWithFragmentShaderFromString:kGPUImageInvertFragmentShaderString])) { return nil; } return self; } @end
很简单,就是使用刚才的着色器代码来设置 filter。这样一个新的滤镜就诞生了~
网路上关于 GPUImage 自定义滤镜 和 GLSL 的资料不是特别多,我斗胆把本身摸索到的理解在这里和你分享,但愿对你有所帮助,若有错误指出欢迎指出,另外,能够去这里查阅 OpenGL GLSL 文档,玩的愉快 (●°u°●) 」
from : http://www.itiger.me/?p=143&utm_source=tuicool