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

回顾

解析(一)
解析(二)
解析(三)
这次介绍的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 分量。如果像素的总大小大于颜色空间中颜色分量数目所需要的空间,则高位将被忽略。

图像颜色空间

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容