您的位置:首页 > 产品设计 > UI/UE

关于iOS开发中图片处理的一些积累(CoreGraphic、CoreImage、GPUImage、OpenGL)

2017-01-15 16:14 513 查看

Core Image

Core Image
前言

Core Graphics

CoreImage

GPUImage

前言

貌似公司最近的项目都是和图片处理有关,拍拍项目中需要将图片处理成buffer传到图像匹配拼接算法中,需要从原图中抠出一定范围的图像再贴到新的背景图中,需要对静态图片进行滤镜操作等等,所以对这方面接触的相对多一些。

抛开各种各样的图像编解码知识,其实图像数据本身就是一个Byte数组,每一个颜色通道都可以用一个UInt32来表示。我们都知道,拿RGBA图像来说,我们可以用一个包含四个元素的a[] = {1,0,0,1}来表示一个红色像素,那这些像素合起来就可以组成一个图像的buffer。UIImage有很多方法可以转成图像buffer.

这里 有一篇对图像进行基本的像素处理的介绍,可以通过修改图像每个像素的颜色通道值来改变图像的整体颜色风格,没错,滤镜处理就是这个原理。

Core Graphics

Core Graphics框架是苹果内置的基于Quartz 2D绘图引擎的绘图API,能够对图像进行一些bitmap操作,总体来说,目前市场上的APP中大部分都用它来写写画画,像是一个画板的感觉,能画出你要的各种东西。这里是一篇很详细的教程。这里(一)(二)详细的介绍了CoreGrapthics的关系和一些使用细节,quartz2D框架在使用时需要我们自己手动来管理内存,而且context上下文的切换是一个非常耗性能的操作,所以使用起来要格外的注意性能的优化。

CoreImage

这是一篇比较早的关于CoreImage框架的介绍,介绍的很详细,包括如何使用CIFiter内置的几种滤镜、使用框架内置的人脸检测、固定颜色的透明度剔除、能够移轴的高斯模糊效果等等。

但是文中关于CIImage概念的介绍有一些误区。CIImage包含生成一个图片的全部数据,不过确切的讲CIImage并不同于UIImage、CGImageRef等是一个图片对象,而是这个图片的描述的抽象(引自官方原话)。

虽然使用CoreImage框架能够满足大部分日常图片滤镜处理之类的需求,而且是系统内置框架,性能上肯定是经过一番考究的,但是其API使用起来比较麻烦,尤其是基于对摄像头数据流的实时滤镜(目前大部分直播APP要求这个功能),所以如果项目中有这方面的需求,这里推荐一个优秀的开源框架GPUImage

GPUImage

GPUImage是目前比较主流的一款开源图像处理框架,有iOS版和安卓版,前一阵又出了swift版,在多平台选择性上没有顾虑。GPUImage隐藏了在iOS中所有需要使用OpenGL ES的复杂的代码,并用极其简单的接口以很快的速度处理图像。GPUImage的性能甚至在很多时候击败了Core Image。

GPUImage最大的特点就是使用简便,它内部封装了许多滤镜,类似亮度滤镜、对比度滤镜、灰度滤镜、双边滤波等等,而且还有许多现成的卡通,黑白版,高斯模糊之类的滤镜效果。可以对stillimage静态图片进行处理,也可以创建camera并随意组合滤镜效果来构建一个摄像头实时滤镜。制作一些常用的滤镜、磨皮美颜效果都很方便。

但是,GPUImage在内存上的处理可能并不是特别友好,使用不当时很容易造成一些内存泄露。我第一次使用GPUImage时有一个需求是一次性对32或64张图片进行处理,滤镜处理后我发现增加的内存没有降下来,测试很久最终定位到如果去掉对结果图的引用,就不会出现这个问题,所以这里需要我们手动拷贝一份结果图数据再去使用,否则可能会因此造成一些中间过程的内存得不到释放而内存激增。下面贴一小段借来的代码示例

- (UIImage *)processUsingGPUImage:(UIImage*)input {
// 1. Create the GPUImagePictures
GPUImagePicture * inputGPUImage = [[GPUImagePicture alloc] initWithImage:input];
UIImage * ghostImage = [self createPaddedGhostImageWithSize:input.size];
GPUImagePicture * ghostGPUImage = [[GPUImagePicture alloc] initWithImage:ghostImage];
// 2. Set up the filter chain
GPUImageAlphaBlendFilter * alphaBlendFilter = [[GPUImageAlphaBlendFilter alloc] init];
alphaBlendFilter.mix = 0.5;
[inputGPUImage addTarget:alphaBlendFilter atTextureLocation:0];
[ghostGPUImage addTarget:alphaBlendFilter atTextureLocation:1];
GPUImageGrayscaleFilter * grayscaleFilter = [[GPUImageGrayscaleFilter alloc] init];
[alphaBlendFilter addTarget:grayscaleFilter];
// 3. Process & grab output image
[grayscaleFilter useNextFrameForImageCapture];
[inputGPUImage processImage];
[ghostGPUImage processImage];
UIImage * output = [grayscaleFilter imageFromCurrentFramebuffer];
return output;
}


前不久,AR技术非常火,各种大大小小的AR眼镜,AR头盔随处可见,笔者在一次冲动消费中得到了一个卖家赠的简易版VR、AR一体眼镜(AR时就是手机放在里边,戴在头上时前边的一个盖子可以打开露出手机摄像头),研究了一下原理,无非就是将手机屏幕分为两块完全相同的区域(如果需要3d效果可以进行一些细小的错位展示)然后通过内置的光学镜片改变人眼的聚焦点,两只眼分别聚焦在两块区域上,出于兴趣,自己基于GPUImage的实施滤镜做了一个小demo,设置了两块相同滤镜的相机预览图层。另外还做了一个基于AVFoundation自定义相机的版本,值得一提的是AVFoundation自定义相机并不支持多图层预览,要想做类似于这种多个预览图层效果的需要我们用在回调中取得每一帧图像然后用OpenGL自己去绘制(苹果中的GLKit简化了openGLES的使用,可以将CVBuffer转成CIImage后直接draw在GLKView中)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: