Skip to content

Commit 5a32729

Browse files
committed
Merge pull request qunten#49 from Daniate/patch-1
Update 图像IO.md
2 parents b47e202 + 78b1e2e commit 5a32729

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

14-图像IO/图像IO.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@
88

99
绘图实际消耗的时间通常并不是影响性能的因素。图片消耗很大一部分内存,而且不太可能把需要显示的图片都保留在内存中,所以需要在应用运行的时候周期性地加载和卸载图片。
1010

11-
图片文件加载的速度被CPU和IO(输入/输出)同时影响。iOS设备中的闪存已经比传统硬盘快很多了,但仍然比RAM慢将近200倍左右,这就需要很小心地管理加载,来避免延迟
11+
图片文件的加载速度同时受到CPU及IO(输入/输出)延迟的影响。iOS设备中的闪存已经比传统硬盘快很多了,但仍然比RAM慢将近200倍左右,这就需要谨慎地管理加载,以避免延迟
1212

13-
只要有可能,试着在程序生命周期不易察觉的时候来加载图片,例如启动,或者在屏幕切换的过程中。按下按钮和按钮响应事件之间最大的延迟大概是200ms,这比动画每一帧切换的16ms小得多。你可以在程序首次启动的时候加载图片,但是如果20秒内无法启动程序的话,iOS检测计时器就会终止你的应用(而且如果启动大于2,3秒的话用户就会抱怨了)。
13+
只要有可能,就应当设法在程序生命周期中不易察觉的时候加载图片,例如启动,或者在屏幕切换的过程中。按下按钮和按钮响应事件之间最大的延迟大概是200ms,远远超过动画帧切换所需要的16ms。你可以在程序首次启动的时候加载图片,但是如果20秒内无法启动程序的话,iOS检测计时器就会终止你的应用(而且如果启动时间超出2或3秒的话,用户就会抱怨)。
1414

15-
有些时候,提前加载所有的东西并不明智。比如说包含上千张图片的图片传送带:用户希望能够能够平滑快速翻动图片,所以就不可能提前预加载所有图片;那样会消耗太多的时间和内存。
15+
有些时候,提前加载所有的东西并不明智。比如说包含上千张图片的图片传送带:用户希望能够平滑快速翻动图片,所以就不可能提前预加载所有的图片;那样会消耗太多的时间和内存。
1616

17-
有时候图片也需要从远程网络连接中下载,这将会比从磁盘加载要消耗更多的时间,甚至可能由于连接问题而加载失败(在几秒钟尝试之后)。你不能够在主线程中加载网络造成等待,所以需要后台线程。
17+
有时候图片也需要从远程网络连接中下载,这将会比从磁盘加载要消耗更多的时间,甚至可能由于连接问题而加载失败(在几秒钟尝试之后)。你不能在主线程中加载网络,并在屏幕冻结期间期望用户去等待它,所以需要后台线程。
1818

1919
###线程加载
2020

21-
在第12章“性能调优”我们的联系人列表例子中,图片都非常小,所以可以在主线程同步加载。但是对于大图来说,这样做就不太合适了,因为加载会消耗很长时间,造成滑动的不流畅。滑动动画会在主线程的run loop中更新,所以会有更多运行在渲染服务进程中CPU相关的性能问题
21+
在第12章“性能调优”我们的联系人列表例子中,图片都非常小,所以可以在主线程同步加载。但是对于大图来说,这样做就不太合适了,因为加载会消耗很长时间,造成滑动的不流畅。滑动动画会在主线程的run loop中更新,它们是在渲染服务进程中运行的,并因此更容易比CAAnimation遭受CPU相关的性能问题
2222

2323
清单14.1显示了一个通过`UICollectionView`实现的基础的图片传送器。图片在主线程中`-collectionView:cellForItemAtIndexPath:`方法中同步加载(见图14.1)。
2424

@@ -93,7 +93,7 @@
9393
9494
GCD(Grand Central Dispatch)和`NSOperationQueue`很类似,都给我们提供了队列闭包块来在线程中按一定顺序来执行。`NSOperationQueue`有一个Objecive-C接口(而不是使用GCD的全局C函数),同样在操作优先级和依赖关系上提供了很好的粒度控制,但是需要更多地设置代码。
9595
96-
清单14.2显示了在低优先级的后台队列而不是主线程使用GCD加载图片的`-collectionView:cellForItemAtIndexPath:`方法,然后当需要加载图片到视图的时候切换到主线程,因为在后台线程访问视图会有安全隐患。
96+
清单14.2显示了在低优先级的后台队列而不是主线程中使用GCD加载图片的`-collectionView:cellForItemAtIndexPath:`方法,然后当需要加载图片到视图的时候切换到主线程,因为在后台线程访问视图会有安全隐患。
9797
9898
由于视图在`UICollectionView`会被循环利用,我们加载图片的时候不能确定是否被不同的索引重新复用。为了避免图片加载到错误的视图中,我们在加载前把单元格打上索引的标签,然后在设置图片的时候检测标签是否发生了改变。
9999
@@ -168,7 +168,7 @@ CFRelease(source);
168168
169169
这样就可以使用`kCGImageSourceShouldCache`来创建图片,强制图片立刻解压,然后在图片的生命周期保留解压后的版本。
170170
171-
最后一种方式就是使用UIKit加载图片,但是立刻会知道`CGContext`中去。图片必须要在绘制之前解压,所以就强制了解压的及时性。这样的好处在于绘制图片可以再后台线程(例如加载本身)执行,而不会阻塞UI。
171+
最后一种方式就是使用UIKit加载图片,但是需要立刻将它绘制到`CGContext`中去。图片必须要在绘制之前解压,所以就要立即强制解压。这样的好处在于绘制图片可以在后台线程(例如加载本身)中执行,而不会阻塞UI。
172172
173173
有两种方式可以为强制解压提前渲染图片:
174174
@@ -318,7 +318,7 @@ CFRelease(source);
318318
319319
###分辨率交换
320320
321-
视网膜分辨率(根据苹果市场定义)代表了人的肉眼在正常视角距离能够分辨的最小像素尺寸。但是这只能应用于静态像素。当观察一个移动图片时,你的眼睛就会对细节不敏感,于是一个低分辨率的图片和视网膜质量的图片没什么区别了。
321+
视网膜分辨率(根据苹果营销定义)代表了人的肉眼在正常视角距离能够分辨的最小像素尺寸。但是这只能应用于静态像素。当观察一个移动图片时,你的眼睛就会对细节不敏感,于是一个低分辨率的图片和视网膜质量的图片没什么区别了。
322322
323323
如果需要快速加载和显示移动大图,简单的办法就是欺骗人眼,在移动传送器的时候显示一个小图(或者低分辨率),然后当停止的时候再换成大图。这意味着我们需要对每张图片存储两份不同分辨率的副本,但是幸运的是,由于需要同时支持Retina和非Retina设备,本来这就是普遍要做到的。
324324
@@ -332,9 +332,9 @@ CFRelease(source);
332332
333333
##缓存
334334
335-
如果有很多张图片要显示,最好不要提前把所有都加载进来,而是应该当移出屏幕之后立刻销毁。通过选择性的缓存,你就可以避免来回滚动时图片重复性的加载了。
335+
如果有很多张图片要显示,提前把它们全部都加载进去是不切实际的,但是,这并不意味着,你在遇到加载问题后,当其移出屏幕时就立刻将其销毁。通过选择性的缓存,你就可以避免来回滚动时图片重复性的加载了。
336336
337-
缓存其实很简单:就是存储昂贵计算后的结果(或者是从闪存或者网络加载的文件)在内存中,以便后续使用,这样访问起来很快。问题在于缓存本质上是一个权衡过程 - 为了提升性能而消耗了内存,但是由于内存是一个非常宝贵的资源,所以不能把所有东西都做缓存。
337+
缓存其实很简单:就是将昂贵计算后的结果(或者是从闪存或者网络加载的文件)存储到内存中,以便后续使用,这样访问起来很快。问题在于缓存本质上是一个权衡过程 - 为了提升性能而消耗了内存,但是由于内存是一个非常宝贵的资源,所以不能把所有东西都做缓存。
338338
339339
何时将何物做缓存(做多久)并不总是很明显。幸运的是,大多情况下,iOS都为我们做好了图片的缓存。
340340
@@ -631,7 +631,7 @@ PNG和JPEG压缩算法作用于两种不同的图片类型:JPEG对于噪点大
631631

632632
除了JPEG和PNG之外iOS还支持别的一些格式,例如TIFF和GIF,但是由于他们质量压缩得更厉害,性能比JPEG和PNG糟糕的多,所以大多数情况并不用考虑。
633633

634-
但是iOS之后,苹果低调添加了对JPEG 2000图片格式的支持,所以大多数人并不知道。它甚至并不被Xcode很好的支持 - JPEG 2000图片都没在Interface Builder中显示。
634+
但是iOS 5之后,苹果低调添加了对JPEG 2000图片格式的支持,所以大多数人并不知道。它甚至并不被Xcode很好的支持 - JPEG 2000图片都没在Interface Builder中显示。
635635

636636
但是JPEG 2000图片在(设备和模拟器)运行时会有效,而且比JPEG质量更好,同样也对透明通道有很好的支持。但是JPEG 2000图片在加载和显示图片方面明显要比PNG和JPEG慢得多,所以对图片大小比运行效率更敏感的时候,使用它是一个不错的选择。
637637

@@ -651,7 +651,7 @@ PNG和JPEG压缩算法作用于两种不同的图片类型:JPEG对于噪点大
651651

652652
* 质量并不是很好,尤其是透明图片。通常看起来更像严重压缩的JPEG文件。
653653

654-
* PVRTC不能用Core Graphics绘制,也不能在普通的`UIImageView`显示,也不能直接用作图层的内容。你必须要用作OpenGL纹理加载PVRTC图片,然后映射到一对三角板来在`CAEAGLLayer`或者`GLKView`中显示。
654+
* PVRTC不能用Core Graphics绘制,也不能在普通的`UIImageView`显示,也不能直接用作图层的内容。你必须要用作OpenGL纹理加载PVRTC图片,然后映射到一对三角形中,并在`CAEAGLLayer`或者`GLKView`中显示。
655655

656656
* 创建一个OpenGL纹理来绘制PVRTC图片的开销相当昂贵。除非你想把所有图片绘制到一个相同的上下文,不然这完全不能发挥PVRTC的优势。
657657

@@ -802,4 +802,4 @@ Xcode包含了一些命令行工具例如*texturetool*来生成PVRTC图片,但
802802
803803
在这章中,我们研究了和图片加载解压相关的性能问题,并延展了一系列解决方案。
804804
805-
在第15章“图层性能”中,我们将讨论和图层渲染和组合相关的性能问题
805+
在第15章“图层性能”中,我们将讨论与图层渲染及图层组合相关的性能问题

0 commit comments

Comments
 (0)