iOS开发日记44-图片及处理

今天博主有一个图片及处理的需求,遇到了一些困难点,在此和大家分享,希望能够共同进步.

图片通常是移动端流量耗费最多的部分,并且占据着重要的视觉空间。合理的图片格式选用和优化可以为你节省带宽、提升视觉效果.

几种图片格式简介:

1.静态图片的编码与解码

JPEG

PNG

WebP

BPG

2.动态图片的编码与解码

GIF

APNG

WebP

BPG

首先谈一下大家耳熟能详的几种老牌的图片格式吧:

JPEG

是目前最常见的图片格式,它诞生于 1992 年,是一个很古老的格式。它只支持有损压缩,其压缩算法可以精确控制压缩比,以图像质量换得存储空间。由于它太过常见,以至于许多移动设备的 CPU 都支持针对它的硬编码与硬解码。

PNG

诞生在 1995 年,比 JPEG 晚几年。它本身的设计目的是替代 GIF 格式,所以它与 GIF 有更多相似的地方。PNG 只支持无损压缩,所以它的压缩比是有上限的。相对于 JPEG 和 GIF 来说,它最大的优势在于支持完整的透明通道。

GIF

诞生于 1987 年,随着初代互联网流行开来。它有很多缺点,比如通常情况下只支持 256 种颜色、透明通道只有 1 bit、文件压缩比不高。它唯一的优势就是支持多帧动画,凭借这个特性,它得以从 Windows 1.0 时代流行至今,而且仍然大受欢迎。

在上面这些图片格式诞生后,也有不少公司或团体尝试对他们进行改进,或者创造其他更加优秀的图片格式,比如 JPEG 小组的 JPEG 2000 、微软的 JPEG-XR、Google 的 WebP、个人开发者发布的 BPG、FLIF 等。

它们相对于老牌的那几个图片格式来说有了很大的进步,但出于各种各样的原因,只有少数几个格式能够流行开来。下面三种就是目前实力比较强的新兴格式了:

APNG

是 Mozilla 在 2008 年发布的一种图片格式,旨在替换掉画质低劣的 GIF 动画。它实际上只是相当于 PNG 格式的一个扩展,所以 Mozilla 一直想把它合并到 PNG 标准里面去。

然而 PNG 开发组并没有接受 APNG 这个扩展,而是一直在推进它自己的 MNG 动图格式。MNG 格式过于复杂以至于并没有什么系统或浏览器支持,而 APNG 格式由于简单容易实现,目前已经渐渐流行开来。

Mozilla 自己的 Firefox 首先支持了 APNG,随后苹果的 Safari 也开始有了支持, Chrome 目前也开始支持 ,可以说未来前景很好。

WebP

是 Google 在 2010 年发布的图片格式,希望以更高的压缩比替代 JPEG。它用 VP8 视频帧内编码作为其算法基础,取得了不错的压缩效果。

它支持有损和无损压缩、支持完整的透明通道、也支持多帧动画,并且没有版权问题,是一种非常理想的图片格式。借由 Google 在网络世界的影响力,WebP 在几年的时间内已经得到了广泛的应用。

看看你手机里的 App:微博、微信、QQ、淘宝、网易新闻等等,每个 App 里都有 WebP 的身影。Facebook 则更进一步,用 WebP 来显示聊天界面的贴纸动画。

BPG

是著名程序员 Fabrice Bellard 在去年 ( 2014 年) 发布的一款超高压缩比的图片格式。这个程序员大家可能有些面生,但说起他的作品 FFmpeg、QEMU 大家想必是都知道的。BPG 使用 HEVC (即 H .265 ) 帧内编码作为其算法基础,就这点而言,它毋庸置疑是当下最为先进的图片压缩格式。

相对于 JP2、JPEG-XR、WebP 来说,同等体积下 BPG 能提供更高的图像质量。另外,得益于它本身基于视频编码算法的特性,它能以非常小的文件体积保存多帧动画。 Fabrice Bellard 聪明的地方在于,他知道自己一个人无法得到各大浏览器厂商的支持,所以他还特地开发了 Javascript 版的解码器,任何浏览器只要加载了这个 76 KB 大小的 JS 文件,就可以直接显示 BPG 格式的图片了。

目前阻碍它流行的原因就是 HEVC 的版权问题和它较长的编码解码时间。尽管这个图片格式才刚刚发布一年,但已经有不少厂子开始试用了.

小Tips

iOS 底层是用 ImageIO.framework 实现的图片编解码。目前 iOS 原生支持的格式有:JPEG、JPEG2000、PNG、GIF、BMP、ICO、TIFF、PICT,自 iOS 8.0 起,ImageIO 又加入了 APNG、SVG、RAW 格式的支持。

在上层,开发者可以直接调用 ImageIO 对上面这些图片格式进行编码和解码。对于动图来说,开发者可以解码动画 GIF 和 APNG、可以编码动画 GIF.

APNG 在文件体积上比 GIF 略有优势,解码时间相差不多。WebP 在体积和解码时间上都具有较大的优势。BPG 在体积上优势最大,但解码时间也最长。这么看来,APNG 和 WebP 都是不错的选择,而 BPG 还有待性能优化.

如何把 GIF 动图保存到相册?

iOS 的相册是支持保存 GIF 和 APNG 动图的,只是不能直接播放。用 [ALAssetsLibrary writeImageDataToSavedPhotosAlbum:metadata:completionBlock] 可以直接把 APNG、GIF 的数据写入相册。如果图省事直接用 UIImageWriteToSavedPhotosAlbum() 写相册,那么图像会被强制转码为 PNG。

将 UIImage 保存到磁盘,用什么方式最好?

目前来说,保存 UIImage 有三种方式:1.直接用 NSKeyedArchiver 把 UIImage 序列化保存,2.用 UIImagePNGRepresentation() 先把图片转为 PNG 保存,3.用 UIImageJPEGRepresentation() 把图片压缩成 JPEG 保存。

实际上,NSKeyedArchiver 是调用了 UIImagePNGRepresentation 进行序列化的,用它来保存图片是消耗最大的。苹果对 JPEG 有硬编码和硬解码,保存成 JPEG 会大大缩减编码解码时间,也能减小文件体积。所以如果图片不包含透明像素时,UIImageJPEGRepresentation(0.9) 是最佳的图片保存方式,其次是 UIImagePNGRepresentation()。

UIImage 缓存是怎么回事?

通过 imageNamed 创建 UIImage 时,系统实际上只是在 Bundle 内查找到文件名,然后把这个文件名放到 UIImage 里返回,并没有进行实际的文件读取和解码。当 UIImage 第一次显示到屏幕上时,其内部的解码方法才会被调用,同时解码结果会保存到一个全局缓存去。据我观察,在图片解码后,App 第一次退到后台和收到内存警告时,该图片的缓存才会被清空,其他情况下缓存会一直存在。

我要是用 imageWithData 能不能避免缓存呢?

不能。通过数据创建 UIImage 时,UIImage 底层是调用 ImageIO 的 CGImageSourceCreateWithData() 方法。该方法有个参数叫 ShouldCache,在 64 位的设备上,这个参数是默认开启的。这个图片也是同样在第一次显示到屏幕时才会被解码,随后解码数据被缓存到 CGImage 内部。与 imageNamed 创建的图片不同,如果这个图片被释放掉,其内部的解码数据也会被立刻释放。

怎么能避免缓存呢?

1. 手动调用 CGImageSourceCreateWithData() 来创建图片,并把 ShouldCache 和 ShouldCacheImmediately 关掉。这么做会导致每次图片显示到屏幕时,解码方法都会被调用,造成很大的 CPU 占用。2. 把图片用 CGContextDrawImage() 绘制到画布上,然后把画布的数据取出来当作图片。这也是常见的网络图片库的做法。

我能直接取到图片解码后的数据,而不是通过画布取到吗?

1.CGImageSourceCreateWithData(data) 创建 ImageSource。

2.CGImageSourceCreateImageAtIndex(source) 创建一个未解码的 CGImage。

3.CGImageGetDataProvider(image) 获取这个图片的数据源。

4.CGDataProviderCopyData(provider) 从数据源获取直接解码的数据。

ImageIO 解码发生在最后一步,这样获得的数据是没有经过颜色类型转换的原生数据(比如灰度图像)。

怎样像浏览器那样边下载边显示图片?

首先,图片本身有 3 种常见的编码方式:

第一种是 baseline,即逐行扫描。默认情况下,JPEG、PNG、GIF 都是这种保存方式。

第二种是 interlaced,即隔行扫描。PNG 和 GIF 在保存时可以选择这种格式。

第三种是 progressive,即渐进式。JPEG 在保存时可以选择这种方式。

在下载图片时,首先用 CGImageSourceCreateIncremental(NULL) 创建一个空的图片源,随后在获得新数据时调用

CGImageSourceUpdateData(data, false) 来更新图片源,最后在用 CGImageSourceCreateImageAtIndex() 创建图片来显示.

时间: 2024-10-20 10:43:10

iOS开发日记44-图片及处理的相关文章

iOS开发项目—07图片拉伸

iOS开发项目—07图片拉伸 一.简单说明 1.代码说明: 图片处理代码: 1 + (UIImage *)resizedImage:(NSString *)name 2 { 3 UIImage *image = [UIImage imageWithName:name]; 4 return [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5]; 5 }

iOS开发需要哪些图片?

1.产品设计图 可以以6的长宽比 750*1134来设计.这些图片用于描述app是什么样子的,这是app开发人员的开发参考. 2.产品切图 将设计师将设计稿切成可以用来开发的图 颜色值 IOS颜色值取 RGB各颜色的值比如某个色值,给予IOS开发的色值为 R:12 G:34 B:56 给出的值就是 12,34,56(有时也要根据开发的习惯,有时也用十六进制) 内部设计细节:1.所有能点击的图片不得小于44px(Retina需要88px)2.单独存在的部件必须是双数尺寸 3.两倍图以@2x作为命名

ios 开发日记 13-剖析网易新闻标签栏视图切换(addChildViewController属性介绍)

iOS开发 剖析网易新闻标签栏视图切换(addChildViewController属性介绍) 时间 2014-06-25 21:45:21  CSDN博客 原文  http://blog.csdn.net/hmt20130412/article/details/34523235 主题 网易iOS开发 本来只是打算介绍一下addChildViewController这个方法的,正好今天朋友去换工作面试问到网易新闻标签栏效果的实现,就结合它,用个小Demo实例介绍一下:(具体解释都写在了Demo里

iOS开发日记31-Block终极篇

今天博主有一个Block的需求,遇到了一些困难点,在此和大家分享,希望能够共同进步. 1.什么是Block      Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block. 2.在iOS开发中,什么情况下使用Block      Block除了能够定义参数列表.返回类型外,还能够获取被定义时的词法范围内的状态(比如局部变量),并且在一定条件下(比如使用__block变量)能够修改这些状态.此

iOS开发日记26-详解时间戳

今天博主有一个时间戳的需求,遇到了一些困难点,在此和大家分享,希望能够共同进步. iOS开发中,我们在很多情况下都会遇到使用当下时间作为参数的情况,这称之为时间戳.在iOSSDK中,与时间戳相关的API主要有三个,NSDate,NSCalendar和NSDate?Components. NSDate 就是一个绝对的时间,可以换算成相对1970s的时差. NSCalendar 顾名思义就是日历,封装了系统如何按照年月日的方式来组织时间,组织时间的方式和地区,时区有很大关系. NSDate?Comp

iOS开发日记16-动画Animation

今天博主有一个动画Animation的需求,遇到了一些困难点,在此和大家分享,希望能够共同进步. iOS开发中的动画分为两种:一种为UIView动画,又称隐式动画,动画后frame的数值发生了变化.另一种是CALayer动画,又称显示动画,动画后模型层的数据不会发生变化,图形回到原来的位置.但是在实际开发中,因为UIView可以相应用户交互,所以UIView动画用的多. 一.UIview的动画 1.实现方式:动画块,block begin //设置动画效果  修改属性值,动画时长等等 conmm

ios开发日记11 对tableView三种计算动态行高方法的分析

tableView是一个神奇的东西,可以这么说,就算是一个初学者如果能把tableView玩的很6,那编一般的iOS的需求都问题不大了.tableView是日常开发中用烂了的控件,但是关于tableView中的自定义cell的动态行高,还是有一些玄机的. AD: tableView是一个神奇的东西,可以这么说,就算是一个初学者如果能把tableView玩的很6,那编一般的iOS的需求都问题不大了.tableView是日常开发中用烂了的控件,但是关于tableView中的自定义cell的动态行高,

iOS开发日记55-通知栏扩展(App Extension)

今天博主有一个App Extension的需求,遇到了一些困难点,在此和大家分享,希望能够共同进步. 总览 扩展 (Extension) 是 iOS 8 和 OSX 10.10 加入的一个非常大的功能点,开发者可以通过系统提供给我们的扩展接入点 (Extension point) 来为系统特定的服务提供某些附加的功能.对于 iOS 来说,可以使用的扩展接入点有以下几个: Today 扩展 - 在下拉的通知中心的 "今天" 的面板中添加一个 widget 分享扩展 - 点击分享按钮后将网

iOS开发之多图片无缝滚动组件封装与使用

经常有园友会问"博主,有没有图片无限滚动的Demo呀?", 正儿八经的图片滚动的Demo我这儿还真没有,今天呢就封装一个可以在项目中直接使用的图片轮播.没看过其他iOS图片无限轮播的代码,也不了解他们的原理,我今天封装这个图片无限轮播是借鉴Web前端中的做法,因为之前写Web前端的时候,实现幻灯片就是这么做的,今天就在iPhone上搞搞.下面的东西是自己写的了,关于轮播的东西这个开源项目也是相当不错的https://github.com/nicklockwood/iCarousel ,