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

2018-04-27 16:27:25 浏览数 (1)

回顾

解析(一)

解析(二)

解析(三)

这次介绍的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,开始处理图像。

代码语言:javascript复制
    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纹理技术是目前解决纹理分辨率与视点距离关系的最有效途径,它会先将图片压缩成很多逐渐缩小的图片,例如一张64_64的图片,会产生64_64,32_32,16_16,8_8,4_4,2_2,1_1的7张图片,当屏幕上需要绘制像素点为20_20 时,程序只是利用 32_32 和 16_16 这两张图片来计算出即将显示为 20_20 大小的一个图片,这比单独利用 32*32 的那张原始片计算出来的图片效果要好得多,速度也更快.

图像数据格式

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

图像颜色空间

0 人点赞