美文网首页iOS技术资料iOS开发部落OpenGL
GPUImage详细解析(四)模糊图片处理

GPUImage详细解析(四)模糊图片处理

作者: 落影loyinglin | 来源:发表于2016-05-31 10:25 被阅读4240次

    回顾

    解析(一)
    解析(二)
    解析(三)
    这次介绍的GPUImageContextGPUImageFramebufferCacheGPUImagePicture

    GPUImageContext

    GPUImageContext是GPUImage对OpenGL ES上下文的封装,添加了GPUImage相关的上下文,比如说Program的使用缓存,处理队列,CV纹理缓存等。

    1、属性介绍

    contextQueue 统一处理队列
    currentShaderProgram 正在使用的program
    context OpenGL ES的上下文
    coreVideoTextureCache CV纹理缓存
    framebufferCache GPUImageBuffer缓存
    shaderProgramCache Program的缓存
    shaderProgramUsageHistory Program的使用历史

    2、方法介绍

    • useAsCurrentContext() 在useAsCurrentContext设置当前上下文的时候,会先判断上下文是否是当前context,不是再设置(为了避免上下文切换的性能消耗,即使设置的上下文是同一个上下文也会消耗性能)

    • sizeThatFitsWithinATextureForSize() 会调整纹理大小,如果超过最大的纹理,会调整为不超过最大的纹理宽高。

    • (GLProgram*)programForVertexShaderString:fragmentShaderString:;
      shaderProgramCache 是program的缓存,由顶点shader和片元shader字符串拼接起来做key。

    • - (void)useSharegroup:(EAGLSharegroup *)sharegroup;
      EAGLSharegroup类管理一个或者多个EAGLContext的OpenGLES资源;这个是一个封闭的类,没有开发者API。负责管理纹理缓存、顶点缓存、帧缓存、颜色缓存。(textures, buffers, framebuffers, and render buffers)

    • - (EAGLContext *)context;返回OpenGL ES2.0的上下文,同时设置glDisable(GL_DEPTH_TEST);,图像处理管道默认不允许使用深度缓存。

    GPUImageFramebufferCache

    GPUImageFramebufferCache是GPUImageFrameBuffer的管理类

    1、属性介绍

    CacheframebufferCache 缓存字典
    framebufferTypeCounts 缓存数量字典
    activeImageCaptureList 正在读取Image数据的GPUImageFrameBuffer列表
    framebufferCacheQueue 缓存队列

    2、方法介绍

    • - (NSString *)hashForSize: textureOptions:onlyTexture:;
      根据size、textureOptions和onlyTexture,创建缓存字符串。
      缓存字符串+当前缓存数量形成framebufferCache缓存的key。
      如果找不到framebufferCache对应的数量,会创建新的缓存。

    • - (void)returnFramebufferToCache:;回收缓存。根据size、textureOptions和onlyTexture,创建缓存字符串,缓存字符串+当前缓存数量形成framebufferCache缓存的key。(之所以会加上数量,是因为缓存字符串不唯一)

    • - (void)addFramebufferToActiveImageCaptureList:;
      - (void)removeFramebufferFromActiveImageCaptureList:
      这两个方法主要用于,当newCGImageFromFramebufferContents()读取帧缓存图像数据时,保持GPUImageFramebuffer的引用。并且读取完数据后,在dataProviderUnlockCallback()方法释放。

    GPUImagePicture

    GPUImagePicture是PGUImage的图像处理类,继承GPUImageOutput,一般作为响应链的源头。

    1、属性介绍

    pixelSizeOfImage 图像的像素大小。
    hasProcessedImage 图像是否已处理。
    imageUpdateSemaphore 图像处理的GCD信号量。

    2、方法介绍

    • - (id)initWithCGImage:smoothlyScaleOutput: 用源图像newImageSource和是否采用mipmaps来初始化GPUImagePicture。
      如果图像大小超过OpenGL ES最大纹理宽高,或者使用mipmaps,或者图像数据是浮点型、颜色空间不对等都会采用CoreGraphics重新绘制图像。
      然后通过glTexImage2D把图像数据发送给GPU,最后释放掉CPU的图像数据。

    • - (BOOL)processImageWithCompletionHandler:; 通知targets处理图像,并在完成后调用complete代码块。在处理开始时,会标记hasProcessedImage为YES,并调用dispatch_semaphore_wait(),确定上次处理已经完成,否则取消这次处理。

    • - (void)addTarget: atTextureLocation:;添加target到响应链。如果hasProcessedImage为YES,表示图像已经处理完毕,直接设置targets的InputSize,并调用newFrameReadyAtTime()通知target。

    DEMO

    用GPUImagePicture处理源图像,用GPUImageTiltShiftFilter处理模糊效果,用GPUImageView显示。

    效果展示

    核心代码

    将GPUImageView设置为self.view,根据face.png,设置GPUImagePicture,然后添加GPUImageTiltShiftFilter到响应链,再把GPUImageView作为响应链的终点,最后调用processImage,开始处理图像。

        GPUImageView *primaryView = [[GPUImageView alloc] initWithFrame:self.view.frame];
        self.view = primaryView;
        UIImage *inputImage = [UIImage imageNamed:@"face.png"];
        _sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage];
        _sepiaFilter = [[GPUImageTiltShiftFilter alloc] init];
        _sepiaFilter.blurRadiusInPixels = 40.0;
        [_sepiaFilter forceProcessingAtSize:primaryView.sizeInPixels];
        [_sourcePicture addTarget:_sepiaFilter];
        [_sepiaFilter addTarget:primaryView];
        [_sourcePicture processImage];
    

    总结

    最近因为直播用户增长太快,忙着优化原来的逻辑,研读源代码的时间变少。
    同时为了写这篇文章,查了一些关于图像资料,末尾附上。
    下一篇文章可能会介绍今年大火的直播APP的一种速成方案,也可能会是GPUImageMovie的介绍。
    喜欢的点一下关注,不迷路。

    MIPMAP

    Mipmap纹理技术是目前解决纹理分辨率与视点距离关系的最有效途径,它会先将图片压缩成很多逐渐缩小的图片,例如一张6464的图片,会产生6464,3232,1616,88,44,22,11的7张图片,当屏幕上需要绘制像素点为2020 时,程序只是利用 3232 和 1616 这两张图片来计算出即将显示为 2020 大小的一个图片,这比单独利用 32*32 的那张原始片计算出来的图片效果要好得多,速度也更快.

    图像数据格式

    kCGImageAlphaLast:alpha 分量存储在每个像素中的低位,如RGBA。
    kCGImageAlphaFirst:alpha 分量存储在每个像素中的高位,如ARGB。
    kCGImageAlphaPremultipliedLast:alpha 分量存储在每个像素中的低位,同时颜色分量已经乘以了 alpha 值。
    kCGImageAlphaPremultipliedFirst:alpha 分量存储在每个像素中的高位,同时颜色分量已经乘以了 alpha 值。
    kCGImageAlphaNoneSkipLast:没有 alpha 分量。如果像素的总大小大于颜色空间中颜色分量数目所需要的空间,则低位将被忽略。
    kCGImageAlphaNoneSkipFirst:没有 alpha 分量。如果像素的总大小大于颜色空间中颜色分量数目所需要的空间,则高位将被忽略。

    图像颜色空间

    相关文章

      网友评论

      本文标题:GPUImage详细解析(四)模糊图片处理

      本文链接:https://www.haomeiwen.com/subject/npucdttx.html