GPUImage源码分析与使用(一)

GPUImage简介

  • GPUImage是链式编程,可以处理图片和视频,支持iOS和Mac。
  • GPUImage1.0和2.0是基于 OpenGL ES 封装,1.0是OC版本,2.0是swift版本,3.0是基于Metal的swift版本。
  • AVFoundation在GPUImage框架中是用来捕捉视频的

CoreImage与GPUImage的对比

  • CoreImage是Apple原生的图片视频处理框架
  • 两者都是基于OpenGL ES封装的框架,在性能上没有太大区别

GPUImage的优势

  • 在iOS4.0和5.0低版本上GPUImage会比CoreImage表现更好
  • GPUImage在视频滤镜处理上会比CoreImage表现更好
  • GPUImage是开源框架,支持自定义滤镜
  • GPUImage源码开源,会比CoreImage更易于使用

CoreImage的优势

  • CoreImage是官方框架,使用方便,不需要担心维护问题,第三方框架会有停止更新维护的情况
  • 还支持CPU渲染
  • 与Metal、spriteKit、SceneKit、Core Animation等官方框架能更好的配合使用
  • 支持人脸识别功能,但是识别功能不是很强大
  • 支持对大图进行处理,GPU的纹理限制是4096*4096,对于超出限制的图片,GPUImage会压缩处理导致损失图片质量,CoreImage会把图片拆解成小图处理

GPUImage的特性

  • 有丰富的输入组件,可以处理图片、纹理、视频、二进制数据、UIElement(UIView、CALayer),可以使用GPUImage拍照、处理纹理图片、给视频或拍摄中的视频添加滤镜、添加水印可以使用UIElement
  • 集成了很多内置滤镜:
    • 颜色类有亮度、饱和度、色度、对比度、白平衡等;
    • 图像类有仿射变换、裁剪、高斯模糊、毛玻璃等;
    • 颜色混合类有透明度混合、纹理混合;
    • 效果类有素描、像素画、旋涡等
  • 有很多输出组件,输出方式有UIView、视频文件、纹理、二进制数据等
  • 灵活的滤镜链,模块化功能

GPUImage框架

      GPUImageOutput,常用的为前4个,最终处理的都是纹理:
* GPUImageVideoCamera(正在录制的视频)
* GPUImageStillCamera(拍摄的照片)
* GPUImagePicture(静态图片)
* GPUImageMovie(一段视频)
* GPUImageMovieComposition
* GPUImageTextureInput(纹理)
* GPUImageRawDataOutput(二进制数据)
* GPUImageUIElement(UIView/UILayer)
* GPUImageColorConversion

Pipeline(管道):

1.GPUImageFilterPipeline

Filters(过滤器/滤镜):

1.Base基类
  • GPUImageFilter,所有Filter父类
  • GPUImageTwoInputFilter
  • GPUImageThreeInputFilter
  • GPUImageFourInputFilter
  • GPUImageTwoPassFilter
  • GPUImageTwoPassTextureSamplingFilter
  • GPUImageFilterGroup
  • GPUImage3x3TextureSamplingFilter
  • GPUImageTwoInputCrossTextureSamplingFilter
  • GPUImageBuffer

内置滤镜:

1. Color processing(色彩处理)
2. Image processing(图像处理)
3. Blends(混合)
4. Effects(效果)

Outputs(输出):

4种输出结果:
1. GPUImageView
2. GPUImageMovieWriter
3. GPUImageTextureOutput
4. GPUImageRawDataOutput

SupportFrameworks:

1. CoreMedia.framework
2. CoreVideo.framework
3. OpenGL ES.framework(1.0和2.0使用,3.0使用Metal)
4. QuartzCore.framework
5. AV Foundation.framework(捕捉视频)

GPUImage类的介绍:

1. GLProgram,shader管理,编译链接
2. GPUImageContext,OpenGL Context管理
3. GPUImageFramebuffer和GPUImageFramebufferCache,buffer管理
4. Source,数据源
5. Pipeline,处理管道
6. Filters,滤镜组合
7. Outputs,输出组件

图片处理示例:

  1. 饱和度滤镜
  • 原图-> GPUImagePicture-> GPUImageSaturationFilter(饱和度滤镜)-> GPUImageView->添加滤镜后的图片
  • 处理流程跟OpenGl ES 一样,只是更具有封装性

GPUImage基类的具体介绍:

GPUImage.h
GPUImage所有需要使用到的类的声明基本上都在这里了

GLProgram:

shader管理
GLProgram.h
1.变量声明,全局变量声明
{
    NSMutableArray  *attributes; //属性
    NSMutableArray  *uniforms; //通道
    GLuint          program,
    vertShader,  //顶点着色器
    fragShader;  //片元着色器
   }
2. 属性声明,记录编译信息等
@property(readwrite, nonatomic) BOOL initialized;//编译信息记录
@property(readwrite, copy, nonatomic) NSString *vertexShaderLog;
@property(readwrite, copy, nonatomic) NSString *fragmentShaderLog;
@property(readwrite, copy, nonatomic) NSString *programLog;
3.初始化,三种初始化方法,第一种是主要方法
/*传入顶点着色器代码和片元着色器代码
可以传入字符串类型,也可以传入文件类型,比如以.vsh/.fsh/.glsl等为后缀等命名的文件
GPUImage里自定义滤镜基本都是使用字符串类型:
*/- (id)initWithVertexShaderString:(NSString *)vShaderString
 fragmentShaderString:(NSString *)fShaderString;- (id)initWithVertexShaderString:(NSString *)vShaderString
 fragmentShaderFilename:(NSString *)fShaderFilename;- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename
 fragmentShaderFilename:(NSString *)fShaderFilename;
4. 添加attribute
- (void)addAttribute:(NSString *)attributeName;
5.attribute和uniform的获取
//获得attribute- (GLuint)attributeIndex:(NSString *)attributeName;
//获得uniform- (GLuint)uniformIndex:(NSString *)uniformName;
6.program操作
- (BOOL)link;- (void)use;- (void)validate;
GLProgram.m
1. 初始化方法,后两种初始化方法都是在获取到本地文件路径后读取glsl字符串,然后调用第一种方法
//传入顶点着色器和片元着色器进行初始化- (id)initWithVertexShaderString:(NSString *)vShaderString
            fragmentShaderString:(NSString *)fShaderString;{
    if ((self = [super init]))
    {
        _initialized = NO;
        
        attributes = [[NSMutableArray alloc] init];
        uniforms = [[NSMutableArray alloc] init];
        program = glCreateProgram();
        
        //拿到着色器代码进行编译
        if (![self compileShader:&vertShader
                            type:GL_VERTEX_SHADER
                          string:vShaderString])
        {
            NSLog(@"Failed to compile vertex shader");
        }
        
        // Create and compile fragment shader
        if (![self compileShader:&fragShader
                            type:GL_FRAGMENT_SHADER
                          string:fShaderString])
        {
            NSLog(@"Failed to compile fragment shader");
        }
        
        //着色器编译后附着到program
        glAttachShader(program, vertShader);
        glAttachShader(program, fragShader);
    }
    
    return self;}
2. 着色器编译方法
- (BOOL)compileShader:(GLuint *)shader
                 type:(GLenum)type
               string:(NSString *)shaderString
{//    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
    GLint status;
    const GLchar *source;
    
    //拿到source
    source =
      (GLchar *)[shaderString UTF8String];
    if (!source)
    {
        NSLog(@"Failed to load vertex shader");
        return NO;
    }
    
    //创建着色器
    *shader = glCreateShader(type);
    glShaderSource(*shader, 1, &source, NULL);
    glCompileShader(*shader);
    
    //获取shader信息
    glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
    if (status != GL_TRUE)
    {
        GLint logLength;
        glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 0)
        {
            GLchar *log = (GLchar *)malloc(logLength);
            glGetShaderInfoLog(*shader, logLength, &logLength, log);
            if (shader == &vertShader)
            {
                self.vertexShaderLog = [NSString stringWithFormat:@"%s", log];
            }
            else
            {
                self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log];
            }
            free(log);
        }
    }   
    
//CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);//    NSLog(@"Compiled in %f ms", linkTime * 1000.0);
 return status == GL_TRUE;}
3. 添加属性addAttribute,使用函数glBindAttribLocation
- (void)addAttribute:(NSString *)attributeName
{
    if (![attributes containsObject:attributeName])
    {
        [attributes addObject:attributeName];
        //glBindAttribLocation函数添加addattribute
        glBindAttribLocation(program,
                             (GLuint)[attributes indexOfObject:attributeName],
                             [attributeName UTF8String]);
    }}
4. 获取attribute和uniform
- (GLuint)attributeIndex:(NSString *)attributeName
{
    return (GLuint)[attributes indexOfObject:attributeName];
}- (GLuint)uniformIndex:(NSString *)uniformName
{
    return glGetUniformLocation(program, [uniformName UTF8String]);
}
5. 链接program
- (BOOL)link
{//    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
    GLint status;
    
    //链接Program
    glLinkProgram(program);
    
    //获取link状态
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    if (status == GL_FALSE)
        return NO;
    
    //link成功之后删除着色器,从program中去着色器信息
    if (vertShader)
    {
        glDeleteShader(vertShader);
        vertShader = 0;
    }
    if (fragShader)
    {
        glDeleteShader(fragShader);
        fragShader = 0;
    }
    
    self.initialized = YES;
//    CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);//    NSLog(@"Linked in %f ms", linkTime * 1000.0);
    return YES;
}
6. 使用和销毁program
- (void)use
{
    glUseProgram(program);}
- (void)validate;{
    GLint logLength;
    
    glValidateProgram(program);
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0)
    {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(program, logLength, &logLength, log);
        self.programLog = [NSString stringWithFormat:@"%s", log];
        free(log);
    }   
}
7. dealloc,删除着色器和program
- (void)dealloc
{
    if (vertShader)
        glDeleteShader(vertShader);
        
    if (fragShader)
        glDeleteShader(fragShader);
    
    if (program)
        glDeleteProgram(program);
       
}
GPUImageContext
GPUImage会有很多context,需要GPUImageContext进行context管理
GLProgram 和 GPUImageContext 不需要使用GPUImage的开发者更改和直接使用,这是GPUImage框架本身使用的
GPUImageFramebuffer/GPUImageFramebufferCache
Framebuffer的管理
//开辟Framebuffer// Initialization and teardown
- (id)initWithSize:(CGSize)framebufferSize;
- (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture;
- (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大王算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值