- 浏览: 1000346 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (675)
- ios (214)
- android-course (5)
- unity3d (7)
- cocos2d (36)
- html5 (3)
- game (5)
- android (42)
- java (57)
- php (12)
- 创业 (10)
- SEO (3)
- 架构 (2)
- 数据库 (3)
- 产品设计 (9)
- 操作系统 (10)
- Web前端 (11)
- 其他 (50)
- GAE (1)
- mac os (8)
- Open Source (2)
- 序列号 (10)
- C (2)
- database (2)
- 算法 (6)
- 设计模式 (1)
- photoshop (1)
- 3dmax (1)
- maya (1)
- opengl (3)
- 游戏设计 (1)
- 趋势 (1)
- cocos2d-x (4)
- shell (3)
- c++ (30)
- lua (5)
- flash (1)
- spring (3)
- mysql (4)
- Git (6)
- xmpp (1)
- cocos2dx (14)
- mac (2)
- 编程规范 (2)
- windows (1)
- linux (5)
- coocs2dx (1)
- ubuntu (2)
- aws (1)
- OPENGLES (1)
- 原画 (1)
最新评论
-
jlees:
Best mobile app testing tool pc ...
iOS + XCode 4 + GHUnit = Mobile TDD+Continuous testing -
ipanda:
楼主,能否给一个Micro CloudFoundry的虚机或者 ...
Cloud Foundry使用及开发向导 -
love_zongming:
谢谢分享。。
visio2007序列号 -
雨花台舞水:
你这才是枪文把
套在 360 黑匣子外面的黑盒子:你被技术型枪稿吓到了么? -
hugh.wang:
改天试试
Mac版魔兽争霸3 1.24e下载
这是一篇译文,(原文"Avoiding Image Decompression Sickness"在此),原文是我看过的非常不错的一篇关于iOS图片显示的一些文章,解决了我的一些疑惑和问题,因此翻译过来分享,为保证一定的通顺性其中一部分内容与原文有些许出入,但我尽量保证了意思的一致性,欢迎指正批评,横线之间为译文,略挫,见谅:
当开始iCatalog.framework的工作时,我发现使用大尺寸图片会引起一些恼人的问题,“大”意味着这个图片有足够大的分辨率(1024×768)来覆盖iPad的整个屏幕,或者覆盖未来Retina Display iPad(如果有的话)的双倍分辨率(2048×1536)屏幕。
想像一个杂志类型的App,一个分页的UIScrollView,每页显示一个UIImageView,一旦某一页进入屏幕区域你就要为这个页创建或者重用一个UIImageView并把它放到scrollView的当前显示区域,即使这个页只有一个像素进入到屏幕区域,你还是要做这些工作。这在模拟器上运行得非常好,但在真机上进行测试,你会发现每次进入下一页时都会有一个明显的延迟。这个延迟来自于将图片从文件解压缩并渲染到屏幕上这一系列的工作。不幸的是UIImage仅在图片将要显示的时候做这个解压工作。
因为添加一个view到当前的view层次结构中必须在主线程上进行,所以图片的解压缩和之后渲染到屏幕上的工作也在主线程进行,这就是这个延迟产生的原因,这个问题也可以在store里的其他有类似这种效果的app中发现。
一般我们使用的图片有两种主要格式,jpeg和png。Apple通常推荐你使用png作为用户界面的图片格式,这些图片会被一个叫pngcrush开源的工具优化(译者注:这个工具就在/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/pngcrush ),这样对于iOS设备就可以在显示时更快地进行解压和渲染。iPad平台上首批出现的杂志应用,比如Wired,就曾用过png作为杂志内容图片的格式,这导致了这个应用的某一版本大小超过了500MB(link)[http://www.cocoanetics.com/2010/05/saturday-morning-breakfast-wired-emag/]
虽然png格式的图片会被事先优化好,但是这并不意味着在所有情况下png都是最佳的图片格式,png对于那些app中自带的图片来说非常好,但是对于要从internet上down下来的图片来说又会怎样呢。png和jpeg这两种格式都有各自的优缺点:
png格式的图片有alpha通道,jpeg则没有。png无损压缩,jpeg允许你选择0-100%的压缩质量。如果需要alpha通道(透明),就只能用png格式。但是如果你不需要一个完美的图片,就可以使用jpeg格式,jpeg格式会忽略那些你看不到的信息,对于大部分的图片可以使用60-70%的压缩质量而不对图片造成明显的影响,对于比如文字那样有"sharp pixels"的图片就可能需要较高的压缩质量,对于照片可以使用较低的压缩质量。
来看一下一个图片的空间消耗:
- 磁盘空间或者通过internet传输所消耗的空间
- 解压缩空间,通常是长X宽X高X4字节(RGBA)
- 当显示在一个view中时,view本身也需要空间来存储layer
对于这里的第一个问题,有一个可能的优化方法:将压缩的文件拷贝到内存中不如映射到内存中,NSData有能力来假设一块磁盘空间是在内存中的,这样当访问这个图片时实际上就是从磁盘访问而不是从内存。据说CGImage知道哪种访问方式是最高效的,UIImage只是将CGImage封装了一下。
对于“将这些像素显示到屏幕上最快要多久?”这个问题,显示一个图片所消耗的时间由以下三个因素决定:
- 从磁盘上alloc/init UIImage的时间
- 解压缩的时间
- 将解压缩后的比特转换成CGContext的时间,通常需要改变尺寸,混合,抗锯齿工作。
要逐一解答各个问题,我们需要一个benchmark来测量。
测试环境和测试内容
我做了一个在iOS设备上运行的benchmark app。对优化和未优化的png图片以及不同尺寸的图片进行了测试,最小时间单位为1ms,不是特别精确,但已经有足够的参考价值了。
测试包括128×96, 256×192, 512×384, 1024×768 和 2048×1536这几种比较有代表性的分辨率,以及优化过的png,未优化的png,压缩质量从10-100%的jpeg这几种格式。benchmark运行在iPad 1+2,iPhone3G,iPhone3G,iPhone4上。
以下为各个设备的硬件参数,来自Wikipedia:
- iPhone 3G:Samsung 32-bit RISC ARM11 620 MHz 处理器 (降频到 412 MHz), PowerVR MBX Lite 3D GPU, 128 MB eDRAM
- iPhone 3GS: Samsung APL0298C05 芯片,ARM Cortex-A8架构,降频到600MHz(从833MHz),集成PowerVR SGX 535 GPU,256 MB eDRAM。
- iPhone 4:基于ARM Cortex-A8的Apple A4芯片,集成 PowerVR SGX 535 GPU,在iPad中频率为1GHz,iPhone 4中的频率没有披露(译者注:不都说是800MHz么,还有512MB RAM都忘了写了,不过这些不说大家也知道)
- iPad 1:1GHz Apple A4芯片 256MB DDR Ram (译者吐槽:原文写的是256GB,吾派的壮哉!)
- iPad 2:1GHz 双核Apple A5芯片,512MB DDR2 RAM
这其中iPad 1和iPhone 4有相同的处理器,在Apple使用自家的芯片后我们看到了性能的明显提升,锁频的A4比之前的Cortex-A8+PowerVR SGC 535 GPU要快一倍
测试数据
1024×768分辨率,90%压缩质量的jpeg图片从加载,解压缩到渲染的时间:
- iPhone 3G: 527 ms
- iPhone 3GS: 134 ms
- iPad: 79 ms
- iPhone 4: 70 ms
- iPad 2: 51 ms
同样是1024×768分辨率,对比优化和未优化的PNG图片
- iPhone 3G: 866 ms – 1032 ms = 快16%
- iPhone 3GS: 249 ms – 458 ms = 快46%
- iPad: 130 ms – 256 ms = 快49%
- iPhone 4: 179 ms – 309 ms = 快42%
- iPad 2: 105 ms – 208 ms = 快49%
3GS的数据充分体现了优化过的png好处:比未优化的快一倍。
以下的图表记录了所有测试数据。
我们首先可以发现同一图表中(相同分辨率)不同的压缩质量有着相似的时间开销,为了数据的完整我还是把所有数据都提供出来:
这两张图表代表了那些可能用在用户界面中的图片。忽略那个古老的设备,我们可一看到所有格式基本都在20ms左右完成显示,这个时间是图片足够小以便即时显示的下限。如果你有一个古老的设备而又不想让你的App很卡的话就要把解压缩工作放到主线程之外进行。
以下的三张图表测试的是那些拥有可以充满iPhone,iPad屏幕的分辨率的图片。
到此之前如果我们忽略古老设备的话,大部分图片都能很快显示,我们可以看到这种条件下使用png图片会对性能造成冲击,我们会更倾向于使用jpeg。
这些分辨率下即使最快的设备每秒也只能处理2(iPad Retina全屏)/10(iPad全屏)张大图片。
即使在非主线程上进行解压缩工作,绘制图片仍需要消耗可观的时间,你可能应该将图片分成小块并使用CATiledLayer来完成显示。
综上我们可一看到红色区域(解压缩)总是消耗最多时间的部分,渲染(绘制)的时间仅取决于分辨率而不是压缩质量,因为像素占组要因素。
通常100%质量的jpeg和优化过的png图片时间开销大致相同。我可以想到两个使用jpeg的理由:1)在设备上不能动态创建优化过的png 2)你只是需要一个完美的图片而不需要考虑磁盘空间开销
横向对比文件大小(文件大小的图表在下面),可以看到从jpeg 10%到jpeg 90%的时间开销线性增长。
在最后这张图表中有一个有趣的问题,在未来可能Retina Display iPad设备上,我们所用的图片的解码时间应当比iPad 2快3-4倍(因为我们需要让图片即时显示在双倍分辨率屏目上,也就是比之前多3倍的像素),而从iPad 1到iPad 2仅有一倍的性能提升,所以这就是iPad 2还不能支持Retina显示的原因。
文件大小
让我们看一下文件大小,优化过的png图片渲染起来更快,但是它减小了文件大小么?
优化过的png格式仅仅对大尺寸图片的文件大小有少量减小,100%压缩质量的jpeg图片文件大小比优化过的png要小,但是100%的质量似乎失去了压缩的目的。我们可一看到使用90%压缩质量的文件要比100%压缩质量的文件小一半还多,jpeg格式的文件大小从10%到90%线性增长,但从90%到100%却有个巨大的增加。
即时性?
对于全屏尺寸的图片我们可以发现一个自从Apple推出平板设备以来就有的一个问题:一个70%压缩质量的全屏尺寸图片在iPad 1上显示需要高达75ms,iPad 2上仍要49ms,完全不能满足即时显示的要求。这与我们60fps的目标相差甚远,13fps或20fps与让人感觉流畅的30祯相比也有很大差距。这会导致在我们拖动scrollview,新图片进入屏幕时,将会卡20分之一秒,之后scrollview必须跳动来追赶上你的手势。
如果排除解压缩的时间,结果就比之前强多了,17-18ms的时间将带来大约55fps的流畅度。有趣的是两代iPad将像素混合到layer的时间没有多少区别,区别仅在解压缩上。
对此我在iCatalog中绘制catalog页的一个简单解决方法就是使用CATiledLayer,并禁用fading。这样就可以在后台线程处理图片的显示而不影响scroll的性能。当然如果快速向右滑动(scroll),相应页的显示就会有一个明显的延迟。这种解决方法的缺点就是很难将横竖屏切换做得很好。
一个更先进的方法就是提前强制解压缩图片。
强制解压缩
当第一次使用图片时,iOS会解压它。通常这个解压缩后的版本将滞留一段时间(内存允许)。尽管这么做没什么意义,但你可以通过将图片渲染成一个新的图片来解压缩这个图片。这样你将在一小段时间内获得两个解压缩的版本。
- (void)decompressImage:(UIImage *)image
{
UIGraphicsBeginImageContext(CGSizeMake(1, 1));
[image drawAtPoint:CGPointZero];
UIGraphicsEndImageContext();
}
这一段代码会解压缩这个image,即时它只有一个像素。
奇怪的是如果UIImage只是通过initWithContentsOfFile创建的,我不能始终保持这个解压缩的版本。所以我必须使用ImageIO framework(iOS 4之后可用) 中提供的一个选项来显式保持这个解压缩的版本:
NSDictionary *dict = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
forKey:(id)kCGImageSourceShouldCache];
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, (CFDictionaryRef)dict);
UIImage *retImage = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
CFRelease(source);
这样初始化图片就可以让解压缩仅发生一次:第一次解压缩消耗很长一段时间,第二次完全不消耗。这其中的关键就是kCGImageSourceShouldCache,你可以为CGImageSource和CGImageSourceCreateImageAtIndex使用这个选项,头文件中是这样说明的:
Specifies whether the image should be cached in a decoded form. The value of this key must be a CFBooleanRef; the default value is kCFBooleanFalse.
如果这个选项设置为NO,绘制图片的时间又会随着解压缩时间增长,如果设置为YES就仅仅解压缩一次。
结论
如果你需要alpha通道或者必须使用PNG格式,那么我推荐你在你的web服务器上安装pngcrush并处理好所有的png图片。其他情况下,高质量的jpeg能带来较小的文件大小以及更快的解压缩和渲染。
事实证明,png格式对于那些使用在UI元素中的小图片来说非常好,但是对于那些全屏显示图片的应用来说则完全不是。替代png的通常是60-80%压缩质量的jpeg,至于压缩质量取多少合适,这取决于你的图片内容。
你可能希望所有显示过的图片都能保持他们的解压缩版本,但是这也将带来大量的内存开销并导致你的App进程被杀掉。此时使用NSCache就是一个很好的解决方案。它可以自动在内存短缺的时候照看好这些图片。
虽然不幸的是我们不能知道一个图片是否需要解压缩,同样一个图片的解压缩版本消失时我们也不会获得任何通知(这或许非常适合提交到Apple的bug反馈网站上)。但幸运的是,通过上述方法访问的解压缩后的图片不会再在解压缩上消耗时间。所以你可以同时在恰当的时间和恰当的条件下使用这种方法而不造成额外的开销。
发表评论
-
Mac上安装Protocol Buffers
2016-09-18 11:29 7621.下载文件 (http://code.google.com ... -
webview点击获取图片
2016-04-01 17:12 772UILongPressGestureRecognizer * ... -
hexo 自动部署脚步
2016-03-29 21:17 876echo "===============star ... -
自定义navigationItem.leftBarButtonItem后,系统默认的手势滑动失效解决方案
2016-03-01 18:01 1231自定义navigationItem.le ... -
UITextView autolayout 高度自适应
2016-02-15 23:26 1345UITextView *t = [[UITextView ... -
腾讯敏捷框架TAPD》研究
2015-11-19 20:47 1371这篇文档是研究心得 ... -
ios image 压缩
2015-11-06 12:09 782- (UIImage *)_scaleToSize:(UII ... -
iphone分辨率图解
2015-11-04 17:33 487iphone分辨率图解 -
IOS中获取各种文件的目录路径的方法
2015-09-24 12:10 604iphone沙箱模型的有四个文件夹,分别是什么,永久数据存储 ... -
Customizing Navigation Bar and Status Bar in iOS 7
2015-08-17 20:23 1548Like many of you, I have been ... -
GCD 深入理解:第一部分
2015-07-24 14:49 710本文翻译自 http://www.raywenderlich ... -
Mac上的抓包工具Charles
2015-05-06 01:09 5269Mac上的抓包工具Charles 分类: IO ... -
如何移除发布版本中的NSLog输出
2015-05-04 20:27 688Phone开发中会经常使用NSLog将一些运行信息输出到终端 ... -
xcode4的环境变量,Build Settings参数,workspace及联编设置
2015-03-27 11:23 868一、xcode4中的环境变量 $(BUILT_PROD ... -
数字签名是什么?
2014-11-25 16:58 574http://www.ruanyifeng.com/blog/ ... -
让你的Xcode更加高效
2014-10-29 00:16 461http://www.tairan.com/archives/ ... -
我所经历的“余额宝”的那些故事
2014-06-08 01:05 701“余额宝”经过不到 ... -
代码手写UI,xib和StoryBoard间的博弈,以及Interface Builder的一些小技巧
2014-05-31 01:25 743最近接触了几个刚入门的iOS学习者,他们之中存在一个普遍 ... -
WWDC 2013 Session笔记 - iOS7中的多任务
2014-05-31 01:24 610这是我的WWDC2013系列笔记中的一篇,完整的笔记列表 ... -
APP被苹果App Store拒绝的79个原因(未完待续)
2014-05-09 10:49 1102作为iOS开发者,估计有很多都遇到过APP提交到App Sto ...
相关推荐
c# 开销跟踪 插入执行开销跟踪,结束开销跟踪,开销时间
任何key,最基础的抽象,都是把键值抽象到内存上,由于按键的特殊性,它可以只需要用 位 来存储硬件上的键值状态。
针对Ashikhmin等提出的纹理合成算法存在时间开销大、容易出现接缝等问题,给出一种改进的基于相关性原理的纹理合成算法。将Ashikhmin算法基于像素点的纹理合成推广到基于块的纹理合成,在匹配过程中采用新的误差度量...
针对图像的传输中可能会产生噪声的影响和传输时间开销过大,导致图像的恢复效果较差的问题,基于数学中熵最大的原理,提出了一种基于熵函数的去噪重构算法。将该算法运用交替方向乘子法(alternating direction ...
针对点到线模型计算量大的问题,提出了一种小波域子矢量的点到线模型的快速算法,并给出了该算法在高光谱图像无损压缩中的方案。该方法通过在点到线模型阶段对矢量进行小波变换,然后选择低频分量,通过调整小波域的...
针对SoC测试中的关键问题——测试数据的压缩,提出...对ISCAS 89标准电路的实验结果表明,与FDR码以及同类型的其他编码方法相比,该编码方法能获得更高的压缩率,从而可以更好地节省测试数据的存储空间和测试应用时间。
一种计算嵌入式应用软件时间和空间开销的方法,孙远,刘伟,在某些嵌入式应用领域,需要事先估计程序在嵌入式控制器上运行的时空开销,避免实际应用时由于软件溢出或软件的时间开销超出限制
sdh原理第三章 主要描述开销sdh原理第三章 主要描述开销sdh原理第三章 主要描述开销sdh原理第三章 主要描述开销sdh原理第三章 主要描述开销
密码学若干算法的计算开销统计,如RSA算法,双线性对运算,EAP认证开销等。
提出了一种在GPU上计算积分图像的方法。积分图像可通过对输入...降低了内存访问开销;提高了GPU线程的工作效率。提出的算法相对以前算法在速度上提高了约两倍。该算法可运用到使用积分图像的图像处理算法的GPU加速中。
高 IO 开销的查询 sql 语句 doc 文档
ospf+rip验证路径开销问题
java运算开销表java运算开销表,解决java性能问题java运算开销表,解决java性能问题
论文:一种微控制器中零开销循环的实现方法。
针对现有缓存策略主要从用户角度对网络性能(缓存命中率、内容获取时延等)进行优化,而没有考虑网络为用户提供服务时的传输开销优化问题,提出了一种最小化内容中心网络中传输开销的协作缓存机制。首先,给出了内容中心...
假设一个系统中有5个进程,它们到达时间和服务时间如表3-1所示,忽略I/O以及其他开销时间,若分别按先来先服务(FCFS)、非抢占及抢占的短进程优先(SPF)、高响应比优先(HRRN)、时间片轮转(RR,时间片=1)、多级...
2019-稀疏三元压缩解决通信开销,考虑下行通信和noniid-Efficient Federated Learning from Non-IID Data1
讲解了计算机磁盘的io原理以及开销,有助于分析持久化存储数据结构的定义
25.OSPF开销值、协议优先级及计时器的修改.topo
为克服小波图像压缩中内存开销大的问题,提出一种基于行的图像压缩算法。该算法是在完成行向小波变换后以累进方式完成列向小波变换,降低了对存储容量的需求,在大数据量图像压缩上优势明显。针对基于行的特点,采用...