ios下UIImage相关开发经验总结

iOS下做和UIImage相关功能有段时间,这里总结列下相关经验。

1. 基本框架image IO

    image IO可以通过URL或者data Provider来生成CGImageSourceRef,然后可以在source上获取第几张图片或者缩略图;根据http://www.mindsea.com/2012/12/downscaling-huge-alassets-without-fear-of-sigkill/文中所讲,使用这种方式比直接加载fullsolutionimage,然后利用core graphics处理要占用更少的内存;这点我还没有明显的发现出来。2014.07.01,今天测试了下,在itouch 4 ios 6上,使用这种方式,内存飙升到50m,相反使用一般加载NSData方式,反而保持在20m。关于这块文件加载方面,个人认为无论是NSData还是前面一种方式,都无法处理超大图片,可以处理的方式应该有两种: a. 使用mmap,会使用虚拟内存 b. 逐步读取,划分块逐步解压缩,逐步缩略。这两种我都没有试,前面一种应该没有问题,后面一种要看相关接口,理论上是可以的。

    image IO可以做图片的逐渐显示,也就是说明了图片可以逐步解压缩的。

    image IO还可以导出图片,CGImageDestinationAddImage方法可以设置内容及图片相关属性,例如exif、gps等属性,这些属性其实也就是ALAssetRepresentation中的metadata属性;http://zacwe.st/blog/saving-jpegs中给出了一个分别使用UIImageJPEGRepresentation和image IO导出图片的比较,image IO相对UIImageJPEGRepresentation节省的比例和我测试差不多,2000*2000的图平均在20%左右,但时间没有那么大差距,基本上接近,最多10%的差距,有时候image IO反而更少。2014.07.02,我目前发现老外的文章也不靠谱啊,目前这点存疑。

   导出图片主要有几个问题,UIImageJPEGRepresentation方法不会导出图片的metadata,UIImageJPEGRepresentation方式会丢失EXIF等信息,一种方式是通过image IO再加回来,一种是自己读取图片二进制,自己手动写bytes,这种一般是利用开源软件,比较麻烦且容易丢掉信息,不推荐使用。image IO这种方式似乎是最好,但是我发现一个比较蛋疼的问题,等传送到应用服务端,服务端再次做处理后,居然比UIImageJPEGRepresentation产生的还大;比较奇怪,需要分析下服务端的实现。

2. UIImage的展示

    UIImage展示在列表中的性能方面,占比较重的分量。个人认为主要影响方面CPU消耗、内存消耗,GPU方面主要保证不要出现blending及离屏绘制,离屏渲染可以被Core Animation 自动触发或是应用程序手动触发;以UIImageView显示为例:

    a. UIImageView并不使用backingstore,而是使用CGImageRef作为CALayer的content。(这里CGImageRef应该是存在RAM内存中的吧)

    b. 通过CATransaction提交改变,在下一个Runloop中,分配内存、读取文件、解压缩、形成bitmap传送给GPU

    在FIC中,讲到iOS 7图片硬件解压缩是没有开放给第三方的,不过个人认为如果说让GPU解压缩的话,解压缩好的图片最好能够缓存,不然可能会存在反复解压缩的情况。所以,通常是异步加载和解压缩,然后再丢给UIImageView做显示。在一些低端设备中,可以异步线程再做一次drawInRect(个人认为这里处理了诸如尺寸拉伸、字节对齐等),这样内存上会比较消耗,但效率会更好点。

  所以,在FIC中提出了针对性的解决方案,它的存储类似sprite sheets,io文件打开只需要一次;直接存储解压缩好的数据,而且还做了字节对齐,CA做字节对齐Copy,我个人理解是保证GPU渲染时不需要对bitmap做额外的数据补齐操作,因为这样的话无论是移动、部分重绘等,都是整齐的,无需额外处理;mmap减少了内存的copy工作(至少减少了kernel到ram),另外使用的是vm,对内存占用有帮助;不过mmap总的来讲,是对大的文件有效率,小的零碎文件效率反而不好。

   FIC的缺陷在于比较适合同样尺寸的小文件,如果文件比较大,解压缩后的数据占用空间比较大。适用场景不普遍,目前不规则的大图片,还是用使用CALayer的方式处理,辅助控制展示时机和drawInRect等方式。

   Core Animation为什么会触发离屏渲染,因为动画是单独线程做的;mask和shadow也有同样的问题,就是mask和shadow并非cpu绘制,从而会触发离屏绘制

3. 图片格式

    jpg和gif是目前主流格式,不过也有替代品。引用一段知乎上的:“Mozilla 社区推崇带有动画的APNG .... Chrome 则推崇自己的 WebP 格式,Animated WebP 则是可以支持动画的 WebP,它包括了真正的(8bit)alpha通道,每一帧还可以按照需要设置成有损或无损,而Gif 只有1bit,相比Gif文件体积可以压缩的更小。 ...  所以Gif 迟迟没有被新的格式取代也是各个社区对各自利益相持的结果,最终还是会被逐步取代。”。目前又出现了用mp4的格式代替gif,真是苦了程序猿。

    不知道谁有Webp的实际应用,有没有什么切身的感受。

Like BPG, it's actually a keyframe format from a video stream - in this case Google's ownWebM/VP8 format.

4. 图片上传

    图片上传的重点是上传方式,目前了解到的就是分块上传,通讯使用socket / http / http pipeline 等,效率最好的应该就是直接使用socket,但是控制起来麻烦点;http的方式最耗流量,时间上也是最长的;在网络情况比较好的情况下,这几种方式差别不大;在网络条件比较差得情况下,socket和http pipeline的双工应该会更好点。和http pipeline相似的应该就是web socket,个人比较看好这种方式。

5. 图片处理

    个人倾向图片处理方面客户端做展示图的处理效果,服务器端做真正图片的处理;节省客户端的资源;不过滤镜等技术,我基本上没有经验,iOS 7倒是带了不少滤镜的功能,不过这块定制性比较强。

 

posted @ 2014-06-28 22:30  wtndcs  阅读(933)  评论(0编辑  收藏  举报