场景很简单,上传图片前压缩图片,节省流量和发图时间。最近看了看 iOS 的静态图片压缩,这里记个笔记。本人之前没学过 iOS 和 Swift,本文是一篇入门文章,描述不到位之处请大家多多批评斧正。 ̄ω ̄=

从这几个方向入手:

  1. 选择图片处理库
  2. 减小图片尺寸
  3. 降低图片质量
  4. 改变图片格式
  5. 降低像素中每个 color component 的 depth

选择图片处理库

我把它放在本文的第一位,因为接下来的代码展示都要用到它。

我选择的是 iOS 自带的 Image I/O,好处是速度快、内存占用小、主流图片格式硬解,Image and Graphics Best Practices - WWDC 2018 和 Image Resizing Techniques 中有介绍。

减小图片尺寸

根据原图的尺寸推测出预期缩略图的尺寸,这个与业务场景强相关,开源的实现比如 Luban,是模仿微信的缩略图尺寸计算逻辑。

首先获取原图尺寸:

let 

然后根据原图尺寸区分几种情况,这里给个 Example,真正用的话可以根据 Luban 改改:

  • 短边与长边比例小于1/3的被算作长图,单独开一条分支。(比例小于 x/x 被算作超长图)
  • 正常比例的图
    • 尺寸较小的,截图等:可视最长边长度,尺寸等比缩小到长边为 1280
    • 尺寸较大的,照片等:可视最短边长度,尺寸等比缩小到短边为 1080 或 1280

计算出预期缩略图的尺寸(thumbWidth, thumbHeight)之后,创建缩略图 CGImage:

let 

快速看了下选项 kCGImageSourceSubsampleFactor 的注释,它能令解码后返回的图片的长宽缩小为原图的 1/n,n ∈ { 2, 4, 8 }。

有点像 libjpeg 支持的 IDCT Scaling,即 jpeg_decompress_struct 里的 scale_num / scale_denom。Skia(Android 用的就是它)的 SkJpegCodec 有提到,libjpeg-turbo 目前对其中的 1/4 和 1/2 有 SIMD 加速。

咳咳,跑远了,要注意一点,用 JPEG 的 IDCT scaling 虽然快,但会导致图像质量变差,我并没有尝试 kCGImageSourceSubsampleFactor 这个选项,不确定它会不会令图像质量变差,有兴趣的同学可以试试。 // TODO 之后补上

就顺便一提,如果想获得微信的缩略图尺寸计算逻辑,可以先从日志入手,自己发几张图,从微信打的日志定位到具体的业务代码。微信日志是非对称加密的。一种方法是修改 xlog 库,拿一台 root 的 Android 手机,把 libwechatxlog.so pull 出来,修改成忽略公钥,再把它 push 回去,替换掉所有 libwechatxlog.so 出现的地方,这样就得到了一个日志不加密的微信,之后 jadx 打开,在代码里搜索相关日志即可。另一种方法是在 Java 层加 hook,不提。

降低图片质量

这节主要是针对 JPEG 格式写的,JPEG 在编码时可以选择质量,iOS (AppleJPEG) 可以指定 0..1.0,而 libjpeg 是 0..100,不要以为它俩之间就是 1:100 的关系,实际我用工具 identify 估算了一下,iOS (AppleJPEG) 的 0.38 约对应于 libjpeg 的 60,0.44 约对应于 70。

这里我们选择 0.38 作为质量参数:

var 

实际场景中,这个值可以受下发的配置和网络状态等环境变量影响,比如我 WIFI 下指定 0.44,4G 下指定 0.38。

改变图片格式

  • 如果想做得简单点,编码格式就两种:JPEG 和 PNG。无透明色选 JPEG,有透明色选 PNG。因为 PNG 格式是无损压缩,一般比 JPEG 格式的图片大,也要更清晰。

透明色由 alpha channel 决定。一般 alpha channel 存在每一个像素里,当然还有其他结构的存储方式,比如 Indexed PNG 会把它写到独立的 tRNS 段。判断图片是否包含 alpha channel 可以用 CGImage Source:

let 

或 CGImage 的 alphaInfo 字段:

let 

来判断。这里提一下 CGImage 的 alphaInfo 字段:

public 

其他字段没啥好说的,premultipliedLast 和 premultipliedFirst 代表“预乘 Alpha”,可以让图片的加载消耗变少,一般在游戏等 CPU (GPU) 密集的场景有用,介绍见 Premultiplied alpha。

压缩成 JPEG 还是 PNG 也就一个参数的区别:

if 

另外我发现还有一个参数 kUTTypeJPEG2000,这个新的 JPEG 格式支持透明色,但推广不起来(估计是不向前兼容的原因)。

以下手段本人还在研究,到时来填坑!!!

  • 如果想做得好点复杂点,比如上传的图片全部编码成 WEBP 或者更好的 HEIF(没错它比 WEBP 还小),那可能需要客户端自己引入新的编码库,还需要服务端支持转码成 JPEG 或 PNG,以便用户下载编辑。好在 HEIF 那么出名,已经有人给我们准备好库了:libheif-rs(突然放出 Rust crate

在 iOS 11 或以上,照片格式已经是 HEIF,iOS 11 或以上也已经支持 HEIF 格式的编解码:

if 

在本文的有损压缩的场景下,HEIF 跟 JPEG 相比,虽然编码耗时长,但输出图片的体积会小很多,网上有许多比较,不提。

由于 HEIF 比同等体积的 JPEG 更为清晰,质量参数可以给大点。

  • 如果想把握未来,可以研究研究同事给我墙裂推荐的 AV1,这坑不填。

降低像素中每个 color component 的 depth

比如 iPhone XS Max 的截屏图片的 color depth 都是 16-bit,降到 8-bit 图片体积会小很多。

let 

多说几句

  1. 很多图片会存一些“元信息”、“元数据”,像拍摄的地理位置、时间、thumbnail 等等,但压缩图片场景需要的一般就两个:color profile 和 orientation。color profile 防止偏色,iPhone 产出的图片一般带有 Display P3,是要写到压缩后的图片里的,这个 Image I/O 会默认自动 copy;指定了 kCGImageSourceCreateThumbnailWithTransform 也会帮你做旋转对称。而大部分多余的信息和数据(地理位置、时间、thumbnail)会被去掉。这块基本不用担心。
  2. 处理图片要小心内存不够用 didReceiveMemoryWarning。
  3. 好的采样算法(比如 Lanczos)会带来更好的图像质量,但一般会消耗会更多的 CPU。目前看来没啥必要。
  4. 要怎么知道 JPEG 图片的质量?很遗憾,质量并不是元信息,要猜测 JPEG 图片质量的话可以参考 ImageMagick。
  5. 要避免重复压缩。加上个预期的缩略图的大小。
if

6. PNG 有没有有损压缩?有,但是不适合本文的场景。TinyPNG 就是有损压缩,开源的有 https://github.com/kornelski/pngquant,思想都是 quantization + indexed。完全可以用 pngquant 自己撸一个不输于 TinyPNG。注意因为出来的图是 indexed,编码时记得 NoFilter。

7. 已经很久很久没有写过博客了。

iOS代码质量要求_图片压缩(iOS)相关推荐

  1. iOS代码质量要求_苹果发布 iOS amp; iPadOS 13.1 beta 4 版本;Dart 2.5正式公布;SwiftUI View的生命周期...

    2019-09-19 由于文章内链接无法直接跳转,可点击左下方"阅读原文"查看相关链接 关键词:Dart 2.5.CTR 苹果发布 iOS & iPadOS 13.1 be ...

  2. 浅谈移动端图片压缩(iOS Android)

    在 App 中,如果分享.发布.上传功能涉及到图片,必不可少会对图片进行一定程度的压缩.笔者最近在公司项目中恰好重构了双端(iOS&Android)的图片压缩模块.本文会非常基础的讲解一些图片 ...

  3. java jpeg压缩解码_图片压缩(iOS)

    场景很简单,上传图片前压缩图片,节省流量和发图时间.最近看了看 iOS 的静态图片压缩,这里记个笔记.本人之前没学过 iOS 和 Swift,本文是一篇入门文章,描述不到位之处请大家多多批评斧正. ̄ω ...

  4. ios 跨域_如何在iOS和Android中建立跨域通信桥

    ios 跨域 I was working on a certain project at work, in which I needed to connect several varying comp ...

  5. 转移到ios下载安卓_转移到ios下载-转移到IOS 安卓版v2.10.0-PC6安卓网

    转移到ios官方版也叫move to ios,是一款连接安卓与苹果系统的工具.转移到ios相当于安卓系统与苹果系统之间的桥梁,实现两者之间的文件.音乐.视频等资源的传输! 软件介绍 Move to i ...

  6. android+多处理器+ios,Fotor - 全能图片处理器 #iOS #Android

    原标题:Fotor - 全能图片处理器 #iOS #Android 对于很多人来说,照片是社交生活不可割舍的一部分,比起文字来,照片让人们的视觉感受更丰富,因此,一张好照片的诞生就显得很有必要了.好的 ...

  7. 转移到ios下载安卓_转移到ios下载官方app-转移到ios手机版v3.0.1 安卓版 - 极光下载站...

    转移到ios官方版是一款非常不错手机备份换机软件工具,使用此软件能快速的安卓手机数据备份到ios系统中,让你在换机后再也不必为数据丢失而烦恼了,而且使用技巧非常简单,有需要的用户欢迎前来本站下载使用! ...

  8. vue图片压缩不失真_图片压缩会失真?快试试这几个无损压缩神器。

    前端通常在做网页的时候 会出现图片加载慢的情况 在这里我通常会将图片进行压缩 但是通常情况下 观众会认为 图片压缩会出现失真的现象 在这里我会向大家推荐几款图片压缩的工具 基本上会实现无损压缩 1.T ...

  9. 拖拽批量上传图片如何保证 顺序_图片压缩神器和图片分割工具,美工设计和运营终于得救了...

    想要快速互联网干货技巧? 请(置顶)星标我们 好不容易写好文案,设计好长图海报,上传到微信公众号,竟然提示上传图片体积不得超过5M,怎么办?怎么办? 不得已,只好又返回Ps里降低图片品质,换成有损格式 ...

最新文章

  1. python基础课程多少钱-培训python多少钱 ?
  2. Keil编译出现sct(7): error: L6236E: No section matches selector - no section to be FIRST/LAST.报错的解决方法
  3. P2085 最小函数值 堆
  4. 年薪50万码农转行卖凉皮,互联网思维又一次颠覆?
  5. 【ZOJ3899】State Reversing 解题报告
  6. FreeRTOS内核实现06:任务延时列表
  7. ft2232驱动安装方法_教你win10系统显卡驱动安装失败的解决方法「系统天地」
  8. 逆置单链表c语言程序,逆置单链表C语言
  9. linux基本命令之chattr与lsattr
  10. FTP连接成功但是无法显示目录的解决方式
  11. message_filters学习笔记
  12. oracle外部表kup-04023,kup-04040访问外部表时
  13. sqlserver2000 详解
  14. Ruby 基础教程(第5版)
  15. 《设计模式的艺术》读书笔记
  16. 高等数学笔记:导函数与原函数关于函数性质的研究
  17. prism 视图发现
  18. Markdown在线写作速成
  19. 数据可视化大屏(柱状图、条形图、情感分析饼图、地域图、词云图、数据表格图、涟漪散点图)
  20. 连接虚拟服务器是什么意思,虚拟主机(服务器)iis连接数是什么意思?超过最大链接...

热门文章

  1. 计算机软件申请专利描述,计算机软件能否申请专利?
  2. Android 返回桌面的操作
  3. 重装 Mac 系统后的安装软件和个人配置[个人习惯]
  4. hacking8信息流邀请码第二关 代码详解
  5. Inside Lucene/超人气搜索引擎学习(2.0)-读取索引
  6. 淘宝直通车为什么要低价引流,低价引流的原理、低价引流的具体操作
  7. src refspec master does not match any问题
  8. 股票自动委托下单html,股票怎么设置自动挂单?股票交易挂单规则
  9. easyui支持ie8浏览器
  10. Unity3D接入第三方插件之微信登录安卓SDK