前言:
app性能的优化一直是一个须要认真对待的问题,特别是项目越复杂这个须要优化的点就更加剧要,谈到性能优化就绕不开图片图形的处理。git
代码实践部分请移步:github
1、图片从磁盘中读入到显示到屏幕全过程
一、图片的加载过程:
- 使用 +imageWithContentsOfFile: 方法从磁盘中加载一张图片或 -[UIImage imageNamed:@"xx.JPG"]此时图片并无解码;
- 初始化完成的UITmage 赋值给 UIImageView;
-
接着一个隐式的 CATransaction 捕获到了 UIImageView 图层树的变化;面试
-
在主线程的下一个 runloop 到来时,Core Animation 提交了这个隐式的 transaction ,这个过程可能会对图片进行 copy 操做,而受图片是否字节对齐等因素的影响,这个 copy 操做可能会涉及如下部分或所有步骤:编程
- 分配内存缓冲区用于管理文件 IO 和解压缩操做;
- 将文件数据从磁盘读到内存中;
- 将压缩的图片数据解码成未压缩的位图形式,这是一个很是耗时的 CPU 操做;
- 最后 Core Animation 中CALayer使用未压缩的位图数据渲染 UIImageView 的图层。
- CPU计算好图片的Frame,对图片解压以后.就会交给GPU来作图片渲染。
由上面的步骤可知,图片的解压缩是一个很是耗时的 CPU 操做,而且它默认是在主线程中执行的。那么当须要加载的图片比较多时,就会对咱们应用的响应性形成严重的影响,尤为是在快速滑动的列表上,这个问题会表现得更加突出。性能优化
二、渲染图片到屏幕上
- iOS设备给用户视觉反馈其实都是经过QuartzCore框架来进行的,说白了,全部用户最终看到的显示界面都是图层合成的结果,而图层便是QuartzCore中的CALayer。
- 一般咱们开发中使用的视图即UIView,他并非直接显示在屏幕上的,你能够把他想象成一个装有显示层CALayer的容器。咱们在在建立视图对象的时候,系统会自动为该视图建立一个CALayer;固然咱们也能够本身再往该视图中加入新的CALayer层。等到须要显示的时候,系统硬件将把全部层进行拷贝,而后按Z轴的高低合成最终的合成效果。
三、图片渲染大体流程
- 在 VSync 信号到来后,主线程开始在cpu上作计算。
- CPU计算显示内容:视图建立、布局计算、图片解码、文本绘制等。
- GPU进行渲染:CPU将计算好的内容提交给GPU,GPU 进行变换、合成、渲染。
- GPU 会把渲染结果提交到帧缓冲区去,等待下一次 VSync 信号到来时显示到屏幕上。
关于渲染更多知识点,例如离屏渲染等由于篇幅太长不利于学习,这部分放在后面app性能篇继续学习。bash
2、图形处理相关框架
经过以上图片加载显示的理论学习,咱们就须要来继续学习一下图形处理的相关理论,毕竟在开发过程当中咱们没法,性能上也不容许,全部图片的显示都用UIimage从磁盘或内存中读入。同时一些界面显示也或多或少要使用到图形处理框架。 网络
一、iOS与图形图像处理相关的框架汇总:
- 界面图形框架 -- UIKit
- 核心动画框架 -- Core Animation
- 苹果封装的图形框架 -- Core Graphics & Quartz 2D
- 传统跨平台图形框架 -- OpenGL ES
- 苹果最新力推的图形框架 -- Metal
- 适合图片的苹果滤镜框架 -- Core Image
适合视频的第三方滤镜方案 -- GPUImage (第三方不属于系统,这里列出来学习)
- 游戏引擎 -- Scene Kit (3D) 和 Sprite Kit (2D)
- 计算机视觉在iOS的应用 -- OpenCV for iOS
毫无疑问,开发者们接触得最多的框架是如下几个,UIKit、Core Animation,Core Graphic, Core Image。下面简要介绍这几个框架,顺便介绍下GPUImage
:app
二、界面图形框架 -- UIKit(穿插使用其余图形处理框架)
- UIKit是一组Objective-C API,为线条图形、Quartz图像和颜色操做提供Objective-C 封装,并提供2D绘制、图像处理及用户接口级别的动画。
- UIKit包括UIBezierPath(绘制线、角度、椭圆及其它图形)、UIImage(显示图像)、UIColor(颜色操做)、UIFont和UIScreen(提供字体和屏幕信息)等类以及在位图图形环境、PDF图形环境上进行绘制和 操做的功能等, 也提供对标准视图的支持,也提供对打印功能的支持。
- UIKit与Core Graphics的关系:
在UIKit中,UIView类自己在绘制时自动建立一个图形环境,即Core Graphics层的CGContext类型,做为当前的图形绘制环境。在绘制时能够调用 UIGraphicsGetCurrentContext 函数得到当前的图形环境;框架
例如:
//这段代码就是在UIView的子类中调用 UIGraphicsGetCurrentContext 函数得到当前的图形环境,而后向该图形环境添加路径,最后绘制。
- (void)drawRect:(CGRect)rect {
//1.获取上下文
CGContextRef contextRef = UIGraphicsGetCurrentContext();
//2.描述路径
UIBezierPath * path = [UIBezierPath bezierPath];
//起点
[path moveToPoint:CGPointMake(10, 10)];
//终点
[path addLineToPoint:CGPointMake(100, 100)];
//设置颜色
[[UIColor whiteColor]setStroke];
//3.添加路径
CGContextAddPath(contextRef, path.CGPath);
//显示路径
CGContextStrokePath(contextRef);
}
复制代码
三、核心动画框架 -- Core Animation
- Core Animation 是经常使用的框架之一。它比 UIKit 和 AppKit 更底层。正如咱们所知,UIView底下封装了一层CALayer树,Core Animation 层是真正的渲染层,咱们之因此能在屏幕上看到内容,真正的渲染工做是在 Core Animation 层进行的。
- Core Animation 是一套Objective-C API,实现了一个高性能的复合引擎,并提供一个简单易用的编程接口,给用户UI添加平滑运动和动态反馈能力。
- Core Animation 是 UIKit 实现动画和变换的基础,也负责视图的复合功能。使用Core Animation能够实现定制动画和细粒度的动画控制,建立复杂的、支持动画和变换的layered 2D视图
- OpenGL ES的内容也能够与Core Animation内容进行集成。
- 为了使用Core Animation实现动画,能够修改 层的属性值 来触发一个action对象的执行,不一样的action对象实现不一样的动画。Core Animation 提供了一组基类及子类,提供对不一样动画类型的支持:
- CAAnimation 是一个抽象公共基类,CAAnimation采用CAMediaTiming 和CAAction协议为动画提供时间(如周期、速度、重复次数等)和action行为(启动、中止等)。
- CAPropertyAnimation 是 CAAnimation的抽象子类,为动画提供一个由一个key路径规定的层属性的支持;
- CABasicAnimation 是CAPropertyAnimation的具体子类,为一个层属性提供简单插入能力。
- CAKeyframeAnimation 也是CAPropertyAnimation的具体子类,提供key帧动画支持。
四、苹果封装的图形框架 -- Core Graphics & Quartz 2D
- Core Graphics(使用Quartz 2D引擎)
- Core Graphics是一套C-based API, 支持向量图形,线、形状、图案、路径、剃度、位图图像和pdf 内容的绘制
- Core Graphics 也是经常使用的框架之一。它用于运行时绘制图像。开发者们能够经过 Core Graphics 绘制路径、颜色。当开发者须要在运行时建立图像时,可使用 Core Graphics 去绘制,运行时实时计算、绘制一系列图像帧来实现动画。与之相对的是运行前建立图像(例如从磁盘中或内存中已经建立好的UIImage图像)。
- Quartz 2D
- Quartz 2D是Core Graphics中的2D 绘制呈现引擎。Quartz是资源和设备无关的,提供路径绘制,anti-aliased呈现,剃度填充图案,图像,透明绘制和透明层、遮蔽和阴影、颜色管理,坐标转换,字体、offscreen呈现、pdf文档建立、显示和分析等功能。
- Quartz 2D可以与全部的图形和动画技术(如Core Animation, OpenGL ES, 和 UIKit 等)一块儿使用。Quartz 2D采用paint模式进行绘制。
- Quartz 2D提供的主要类包括:
- CGContext:表示一个图形环境;
- CGPath:使用向量图形来建立路径,并可以填充和stroke;
- CGImage:用来表示位图;
- CGLayer:用来表示一个可以用于重复绘制和offscreen绘制的绘制层;
- CGPattern:用来表示Pattern,用于重复绘制;
- CGShading和 CGGradient:用于绘制剃度;
- CGColor 和 CGColorSpace;用来进行颜色和颜色空间管理;
- CGFont, 用于绘制文本;
- CGPDFContentStream、CGPDFScanner、CGPDFPage、CGPDFObject,CGPDFStream, CGPDFString等用来进行pdf文件的建立、解析和显示。
五、适合图片的苹果滤镜框架 -- Core Image
-
Core Image 与 Core Graphics 偏偏相反,Core Graphics 用于在运行时建立图像,而 Core Image 是用来处理已经建立的图像的。Core Image 框架拥有一系列现成的图像过滤器,能对已存在的图像进行高效的处理。函数
-
Core Image 是 iOS5 新加入到 iOS 平台的一个图像处理框架,提供了强大高效的图像处理功能, 用来对基于像素的图像进行操做与分析, 内置了不少强大的滤镜(Filter) (目前数量超过了180种), 这些Filter 提供了各类各样的效果, 而且还能够经过 滤镜链 将各类效果的 Filter叠加 起来造成强大的自定义效果。
- 一个 滤镜 是一个对象,有不少输入和输出,并执行一些变换。例如,模糊滤镜可能须要输入图像和一个模糊半径来产生适当的模糊后的输出图像。
- 一个 滤镜链 是一个连接在一块儿的滤镜网络,使得一个滤镜的输出能够是另外一个滤镜的输入。以这种方式,能够实现精心制做的效果。
- iOS8 以后更是支持自定义 CIFilter,能够定制知足业务需求的复杂效果。
-
Core Image 的优势在于十分高效。大部分状况下,它会在 GPU 中完成工做,但若是 GPU 忙,会使用 CPU 进行处理。若是设备支持 Metal,那么会使用 Metal 处理。这些操做会在底层完成,Apple 的工程师们已经帮助开发者们完成这些操做了。
- 例如他能够根据需求选择 CPU 或者 GPU 来处理。
// 建立基于 CPU 的 CIContext 对象 (默认是基于 GPU,CPU 须要额外设置参数)
context = [CIContext contextWithOptions: [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:kCIContextUseSoftwareRenderer]];
// 建立基于 GPU 的 CIContext 对象
context = [CIContext contextWithOptions: nil];
// 建立基于 GPU 的 CIContext 对象
EAGLContext *eaglctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
context = [CIContext contextWithEAGLContext:eaglctx];
复制代码
-
Core Image 的 API 主要就是三类:
- CIImage 保存图像数据的类,能够经过UIImage,图像文件或者像素数据来建立,包括未处理的像素数据。
- CIFilter 表示应用的滤镜,这个框架中对图片属性进行细节处理的类。它对全部的像素进行操做,用一些键-值设置来决定具体操做的程度。
- CIContext 表示上下文,如 Core Graphics 以及 Core Data 中的上下文用于处理绘制渲染以及处理托管对象同样,Core Image 的上下文也是实现对图像处理的具体对象。能够从其中取得图片的信息。
六、适合视频的第三方滤镜方案 -- GPUImage
- GPUImage是一个基于OpenGL ES 2.0的开源的图像处理库,优点:
- 最低支持 iOS 4.0,iOS 5.0 以后就支持自定义滤镜。在低端机型上,GPUImage 有更好的表现。
- GPUImage 在视频处理上有更好的表现。
- GPUImage 的代码已经开源。能够根据本身的业务需求,定制更加复杂的管线操做。可定制程度高。
参考文章: