Skip to content

Instantly share code, notes, and snippets.

@Vokinloksar
Last active October 16, 2018 08:45
Show Gist options
  • Save Vokinloksar/fbc3bd18b3ef073f7d911da43c144c2d to your computer and use it in GitHub Desktop.
Save Vokinloksar/fbc3bd18b3ef073f7d911da43c144c2d to your computer and use it in GitHub Desktop.

ADMIN/WEB 图片显示&size优化 tradeoff分析

影响图片size的因素

  • Quality (q_85...)
  • Dimension
  • DPR (1.0, 2.0 - iPhone6/7/8, 3.0 - iPhone6/7/8 Plus/iPhoneX)
  • Format (jpg, png, webp)

基本概念(术语)

Format

  • 除非特殊情况, 默认上传的图片都会转化为 .jpg 格式
  • Admin图片链接部分参数说明
    • f_auto,Cloudinary会自动将图片转换为浏览器能接收的最优格式,例如支持 webp的 Chrome
    • fl_lossy,在对显示影响较小的情况下,Cloudinary会对图片进行有损压缩
    • c_fill,对图片填充处理,

Quality

  • 图片 quality默认为90,也即是 q_90, cloudinary 显示的图片size是已经压缩过得size (目前只适用.webp)

DPR

物理像素(physical pixel)

一个物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值。

设备独立像素(DPR: density-independent pixel)

设备独立像素(也叫密度无关像素),代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素。

设备像素比(device pixel ratio )

设备像素比(简称dpr)定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到: 设备像素比 = 物理像素 / 设备独立像素 // 在某一方向上,x方向或者y方向

在javascript中,可以通过 window.devicePixelRatio 获取到当前设备的dpr。
在css中,可以通过 -webkit-device-pixel-ratio-webkit-min-device-pixel-ratio-webkit-max-device-pixel-ratio 进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。 DPR Illustration 以 iPhone6为例:

  1. iPhone 6 display is 4.7 inches in size with a 16:9 resolution of 1334x750
  2. 设备宽高为375×667,也即是设备独立像素(比如: css像素)。
  3. 其 dpr为2,即1个css像素对应 4个物理像素(1:4),所以实际size为@2,750×1334。

分析

以 Klook 首页 Banner图片 (1920x600, 851.4 KB JPG) 为例

图片类型 参数 大小 相对比率 备注
JPG 不带参 853kb 444% 默认图片,尺寸为 1920 * 600,体积大
WEBP 不带参 192kb 100% webp 格式的体积只有 jpg格式的 22.5%
WEBP q_100 1.3mb 693% 相对于默认的 q_90而言,体积特别大 TBD
WEBP q_85 128kb 67% 目前 Klook的图片压缩质量大部分为 q_85
WEBP q_60 59.5kb 31% 发梢开始有点模糊了,图片显示质量下降相对明显了(非 retina屏)
WEBP dpr_1.0,w_1920,h_600 192kb 31% dpr参数需要带 w和 h才能生效,默认为1.0,体积和尺码等价于不带参数的 webp
WEBP dpr_2.0,w_1920,h_600 364kb 189.6% 尺码@2,3840 * 1200
WEBP dpr_3.0,w_1920,h_600 606kb 315.6% 尺码@3,5760 * 1800
  1. 当图片像素点个数小于屏幕像素点(物理像素)个数时,图片会就近取色以填充像素,从而造成模糊
    • 比如设定css像素为 20×20,20×20的图片在 retina屏下,会被填充为屏幕物理像素大小的图片,也即 40×40 从小到大
  2. 当图片像素点个数大于屏幕像素点(物理像素)个数时,图片会通过算法(downsampling)去实现缩小,如此会造成图片缺少一些锐利度或者色差,但不会模糊
    • 比如设定css像素为 20×20,40×40的图片在普通屏下,会被压缩为屏幕物理像素大小的图片,也即 20×20 从大到小
  3. 只有当图片像素点个数与屏幕像素点(物理像素)个数 1:1 关系,图片才能获得最优的清晰展示
    • 比如为了获得 DPR 2.0,css像素为 40×40 的清晰图片展示,需要原始size为80×80的图片,以免被有损放大/缩小

因此,dpr主要作用于 Retina屏下,保证图片的显示效果,而提高高清屏显示效果,需要上传更大的原始size图片(比如@2图)

实现

  • 自适应DPR
    let connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection,
        type = connection && connection.effectiveType  || '4g', // 网络状态,需兼容不支持该接口的浏览器情况
        drp = window.devicePixelRatio || 1,
        drpVal = type === '4g' ? drp : 1,
        imgUrl = `https://res.klook.com/image/upload/fl_lossy.progressive,q_85,dpr_${drpVal},f_auto/c_fill,,/v1526541190/banner/y0ehj286wxl4lirq2rdb.webp`
    @media (-webkit-max-device-pixel-ratio: 3) {
      i {
          background-image: url('...@3.jpg')
      }
    }
    <img srcset="elva-fairy-320w.jpg,
                elva-fairy-480w.jpg 1.5x,
                elva-fairy-640w.jpg 2x"
                src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy">
    • 脚本填补 - 先有模糊的图片, 然后再懒加载出比较大的原图,预先加载往后的图片

限制

f_auto & dpr 参数只有使用cloudinary CDN 才可以支持。目前无法使用

建议,尽可能的对部分比较重要位置的图片至少进行@2倍的图片上传,并在展示上做高清处理

Links

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment