回顾
GPUImage源码解析、图片模糊、视频滤镜、视频水印都已经介绍过,这次带来的是给视频添加文字水印、动态图像水印。
效果展示
“我是水印”的文字,还有心形气泡组成的水印。
处理中的动态图,上面是进度,下面是文字水印:“我是水印”,动态图像水印:心形气泡。
核心思路
- 1、UIView上面有UILabel(文字水印)和UIImageView(图片水印),再通过GPUImageUIElement把UIView对象转换成纹理对象,进入响应链;
- 2、视频文件的图像数据通过GPUImageMovie进入响应链;
- 3、GPUImageDissolveBlenderFilter合并水印图像和视频,把数据传给响应链的终点GPUImageView以显示到UI和GPUImageMovieWriter以写入临时文件;
- 4、视频文件的音频数据通过GPUImageMovie传给GPUImageMovieWriter以写入临时文件;
- 5、最后临时文件通过ALAssetsLibrary写入系统库。
具体细节
1、GPUImageUIElement
GPUImageUIElement继承GPUImageOutput类,作为响应链的源头。通过CoreGraphics把UIView渲染到图像,并通过glTexImage2D绑定到outputFramebuffer指定的纹理,最后通知targets纹理就绪。
2、GPUImageOutput和GPUImageFilter
本次demo主要用到了frameProcessingCompletionBlock属性,当GPUImageFilter渲染完纹理后,会调用frameProcessingCompletionBlock回调。
3、响应链解析
- 1、当GPUImageMovie的纹理就绪时,会通知GPUImageFilter处理图像;
- 2、GPUImageFilter会调用frameProcessingCompletionBlock回调;
- 3、GPUImageUIElement在回调中渲染图像,纹理就绪后通知 GPUImageDissolveBlendFilter;
- 4、frameProcessingCompletionBlock回调结束后,通知 GPUImageDissolveBlendFilter纹理就绪;
- 5、GPUImageDissolveBlendFilter收到两个纹理后开始渲染,纹理就绪后通知GPUImageMovieWriter; 如图
总结
本篇的内容与上一篇视频水印有类似的地方。GPUImageUIElement是新的知识点,但是如果对CoreGraphics和OpenGL ES熟悉可以秒懂。
附上代码
思考题
思考1:响应链解析中的GPUImageFilter有什么作用?是否可以去掉? 思考2:frameProcessingCompletionBlock里面需要做什么样的操作?为什么? 思考3:能否对图像水印进行复杂的位置变换?
答案
思考1:目的是每帧回调;去掉会导致图像无法显示。 思考2:回调需要调用update操作;因为update只会输出一次纹理信息,只适用于一帧。 思考3:在回调中对UIView进行操作即可;或者使用GPUImageTransformFilter。