内容简介:首先要说的是,关于图片的编码原理,压缩算法这些都是很专业的领域,作为一个小前端来讲,知道一般的应用场景和一般的特性就可以了。矢量图: 前端最常见的矢量图是 SVG。关于 SVG 可以看SVG 基础 这篇文章,SVG 适用于包含简单的几何图形的图像,因为 SVG 缩放不失真,所以 SVG 最适合用于高分辨率屏幕和需要以不同尺寸显示的图像。栅格图像:
首先要说的是,关于图片的编码原理,压缩算法这些都是很专业的领域,作为一个小前端来讲,知道一般的应用场景和一般的特性就可以了。
基本概念
矢量图与栅格图像
- 矢量图:形使用线、点和多边形来表示图像。
- 栅格图像: 通过对矩形格栅内的每个像素的值进行编码来表示图像。
矢量图: 前端最常见的矢量图是 SVG。关于 SVG 可以看SVG 基础 这篇文章,SVG 适用于包含简单的几何图形的图像,因为 SVG 缩放不失真,所以 SVG 最适合用于高分辨率屏幕和需要以不同尺寸显示的图像。
栅格图像:
- 由一个个的像素栅格组成;
- 每个像素都编码了颜色和透明度信息;
- 使用不用的压缩算法(不同的图片格式),以减小图像的文件大小。
因为源数据太大,一般在网页中使用的是经过压缩的文件,下面是一个 JPG 文件的压缩和解压的过程:
这里涉及两个过程:
- 编码: 源数据编码得到 JPG 文件;这个 JPG 文件,用于存储和出传输。
- 解码: 要显示这个图像的时候,解码 JPG 文件内容得到源数据。
有损压缩无损压缩
继续以上面的 JPG 编解码为例。源数据是 2 维“像素”栅格 ,比如,一个 10 × 10 的图像便有 100 个像素。每个像素又存储了 RGBA 的值: (R) 红色通道、(G) 绿色通道、(B) 蓝色通道和 (A) alpha(透明度)通道。每个通道 8 位,即每个像素 4 个字节。 浏览器在拿到 jpg 文件之后,解码得到一个同原始数据一样的像素栅格序列,也要为每个像素分配 4 个字节的内存(无论使用什么格式传输,最后还原数据会和原始数据一样大)。
那么, 如果浏览器可以解码得到原始数据,则为 无损压缩 。如果为了得到更小的文件,压缩过程中可能会丢弃一些人眼不能察觉的信息,而且这个过程是不可逆的,那么浏览器解码也就无法得到原始数据,这种压缩方式便是 有损压缩 。
对于栅格图像要根据不同的使用场景选择合适格式,接下来探究一些常见的这几种图片格式。
常见图片格式
JPG/JPEG
可能是目前世界上使用最广泛的图像格式,特点:
- 不支持透明;
- 有损压缩。
JPEG 适合于色彩丰富,线条感比较弱的图片,比如大的背景图,banner 图等等。JPEG 是有损压缩(也有无损的 JPEG,支持不够广泛),压缩时质量级别越低体积越小,图片也越模糊。所以,在使用时,需要根据需要选择合适的质量级别。
优化
JPEG 有多种不同的压缩模式, 比如常见的基线(顺序)JPEG 和渐进式 JPEG (PJPEG)。
基线 JPEG(大多数图像编辑和优化 工具 的默认设置)以相对简单的方式进行编码和解码:从上到下。 在连接速度缓慢或不稳定的情况下加载基线 JPEG 时,用户会先看到图像的顶部,然后随着图像加载逐渐看到图像的其他部分。 盗用谷歌图:
基线 JPEG 的加载方式是从上到下,而渐进式 JPEG 是从模糊到清晰。
渐进式 JPEG 将图像分成多次扫描, 第一次扫描以模糊或低质量设置显示图像,后续扫描逐步提高图像质量。 我们可以将这个过程看作“渐进式”提高图像质量。 每次“扫描”图像都会增加细节的清晰程度,最后合并为全画质图像。
渐进式 JPEG 可以在没有下载完图片就可以看到最终图像的大致轮廓,一定程度上可以提升用户体验。
与基线 JPEG 相比,渐进式 JPEG:
- 比较大的图,有更高压缩率;
- 需要更多的 CPU 资源去解码。
使用基线 JPEG 相比还是渐进式 JPEG,需要我们根据场景选择,在文件大小,网络延迟和 CPU 消耗之间做一个权衡。
关于渐进式 JPEG 扯点别的: 渐进式 JPEG 采用的扫描算法有个学名 -- 隔行扫描 ,更多信息请看维基百科 的介绍。
隔行扫描的效果是下面这样的,感觉这张图专业而且很形象:
除了 JPEG 可以支持隔行扫描外,PNG 和 GIF 也有支持,便是交错式 PNG\GIF。
优缺点
优点:
- 使用高效的压缩算法,图片体积小;
- 色彩丰富,可以支持 24bit 真彩色;
- 压缩的质量级别可以控制。
缺点: 对于线条感较强,颜色对比强烈的图,JPG 的压缩通常会更易让人感觉到模糊;另外对于有透明度要求的图 JPG 完全无能为力,这个时候我们就要考虑 PNG 了。
PNG
特点:
- 支持透明;
- 除了选择调色板的大小外,PNG 不采用任何有损压缩算法。
因为 PNG 是一种无损压缩的高保真的图片格式(调色板大小的问题,下面讨论),所以,可以保存更多的细节,同时体积也就更大。
优化
既然 PNG 是无损压缩为什么一些工具还声称可以压缩 PNG 呢?比如最知名的 tinypng(也有人称为熊猫网) 。
看看 tinypng 官网咋说的:
How does it work?
Excellent question! When you upload a PNG (Portable Network Graphics) file, similar colors in your image are combined. This technique is called “quantization”. By reducing the number of colors, 24-bit PNG files can be converted to much smaller 8-bit indexed color images. All unnecessary metadata is stripped too. The result better PNG files with 100% support for transparency. Have your cake and eat it too!
这儿需要铺垫一下 PNG 的三种形式:PNG8,PNG24 和 PNG32。 PNG8 和 PNG24 主要的区别有:
- 最直观的的就是颜色位数的不同。每个像素点的数据,PNG8 需要 8 位即一个字节,而 PNG24 使用 24 位也就是三个字节:RGB 三个通道各需一个字节。
- 因为位数不同,能表示的颜色数量不同。PNG8 最多只能表示 256 色,而 PNG24 支持 24 位真彩色。
- 压缩方式不同。PNG8 采用调色板 + 索引值的方式,PNG24 无调色板,使用点阵存储色值。
- 半透明支持不同。PNG8 调色板中每种颜色使用 RGBA 四通道表示,支持 半透明,而 PNG24 每个像素只有 RGB 三通道,所以 PNG24 不支持半透明。
PNG24 与 PNG32:
- PNG32 相比 PNG24 多了一个 Alpha 通道,支持半透明。
- 很多时候不区分 PNG24 和 PNG32。比如 PS 中,只有 PNG24 的选项,如果勾选了透明选项则是表示是 PNG32。
我们回过头继续说 PNG 的优化,正如 tinypng 官网所说,他们采用的优化便是把 PNG24/PNG32 转为 PNG8。这种优化方式也称为 PNG 的有损压缩 。
平常使用中一般选择使用 PNG8,如果 PNG8 的效果太差,则建议改为使用其他格式,因为 PNG24 会大很多。
PNG 还有一个上文提到过的优化策略 —— 交错式 PNG , 和渐进式 JPEG 的效果和原理相同,这里就不过多介绍了。
优缺点
- 优点: 无损、质量高、支持透明。
- 缺点: 体积大。
GIF
概述:
- 支持动画,也支持静态 GIF;
- 最多支持 256 色;
- 无损压缩;
- 支持全透明,不支持半透明。
对待 GIF 的原则一般是, 除了动画外不使用 GIF 。因为,对于静态 GIF 来说,PNG8 显得更加优秀:
- 同样的调色板最多 256 色,PNG8 体积更小;
- 同样的支持透明, PNG8 支持半透明;
- PNG8 同样也是无损压缩(二者都可以改变调色板颜色数量来有损压缩)
但是, PNG8 也并不是总比 GIF 小,当图片小到一定尺度的时候, GIF 会比其他格式的图都会小,比如: 这样一张二维码:
因为,二维码只有黑色和白色,所以把调色板的颜色数量设为 2, 导出 256 × 256 的图(单位:像素):
- PNG8: 2.457KB
- GIF: 3.402KB
导出为 50 × 50 的图:
- PNG8: 648B
- GIF: 425B
GIF 如下,还可以扫码:
而当导出更小的图时, GIF 的优势越明显。当导出尺寸为 20 × 20 的时候,二者的体积就差了一倍。
由此,也就引出了 GIF 的另外的用途: 颜色简单尺寸超小的图,可以使用 GIF ,比如:
- 一些小二维码;
- 一些 icon 或 logo;
- 数据上报,页面监控使用 1 × 1 px 的 GIF。
优缺点
- 优点: 支持动画。
- 缺点: 动画的体积大,也很消耗性能(因为 GIF 多帧之间没有压缩处理)。
WebP
WebP 是由 Google 开发的一个年轻的图像格式。同时, WebP 也是很优秀的:
- WebP 有损文件比 JPEG 文件小 25% 至 34%;
- WebP 无损文件比 PNG 文件小 26%;
- 支持动画。
所以我们基本可以认为, 能使用 WebP 的时候就使用 WebP 是一条很有效的优化策略。
更多信息可以看这里 Google I_O 2013 - WebP (感觉视频的字幕是校对过的,很准确)。
WebP 最大的问题是兼容问题:
从图中可以看到旧浏览器和 苹果家的产品 基本不支持。
优化
关于 WebP 的优化,基本就是解决兼容问题。
嗅探
查看浏览器支不支持,最简单的方法就是给 img 元素一个 .webp 的图像(一般使用 1×1px 大小 webp 的 base64 字符串),看看是否能正常加载。基本原理如下:
var image = new Image();
image.onload = function() {
// 支持
};
image.error = function() {
// 不支持
};
image.src = 'data:image/webp;base64,xxxxx';
复制代码
比如淘宝就在使用类似的技术,
<picture> 标签
HTML5 的 <picture> 给图片的各种扫操作提供了可能。
<picture> <source srcset="xxx.webp" type="image/webp"> <img src="xxx.jpg" alt=""> </picture> 复制代码
后端解决
Accept 请求头
对于上面的方案,仍需要前端去判别 jpg 和 webp。当然,这个判断任务可以由后端完成:
前端:
<img src="/xxx/avatar_url"> 复制代码
对于支持 WebP 的浏览器,在 HTTP 的请求头中会包含:
Accept: image/webp,xxxxxxx 复制代码
server 端据此返回合适的资源。
User-Agent
通常我们从业务服务器只请求到了图片的 URL,而图片资源却放在了 CND 上。这种情况下可能需要业务服务器返回合适的 CDN 资源。 比如, YouTube 就是利用 AJAX 请求的 User-Agent 来判断, 对于兼容 WebP 的浏览器返回 WebP 资源 URL。
CDN
目前很多 CND 都提供了 WebP 的格式转换功能,通过参数可以指定不同的格式。与上文提到的几种方式搭配,口味更佳。比如淘宝:
chrome 中使用:
https://img.alicdn.com/xxxxxxxxx.jpg_.webp 复制代码
在 IE 中使用:
https://img.alicdn.com/xxxxxxxxx.jpg 复制代码
YouTube 也是类似,只不过图片的 URL 是由后端直接返回,无需前端再拼参数。
另外,有些 CND 提供自动判断功能,会根据情况返回合适的图片。这种情况下,所有的格式转换和兼容判断问题由 CDN 完成,前端和后端,都无需在做额外的工作。
优缺点
- 优点: 支持有损压缩,无损压缩和动画,且体积更小。
- 缺点:兼容性差,性能差(上文外链视频中数据:相对 JPEG 编码慢 5-10 倍,解码慢 1.3 倍)。
SVG
关于 SVG 基础看SVG 基础。
特点:
- 矢量图,放大不失真;
- 纯文本文件,文件体积更小,可压缩性更强;
- 可嵌入 HTML 中;
- 可以使用 CSS 修改图片内容。
优化
使用 AI 和 Sketch 中导出的 SVG 包含大量元数据,例如图层信息、空属性,多余的空字、注解和 XML 命名空间等,这些在浏览器中都是不需要的。因此使用一些工具可以去掉这些没有必要的信息,比如 SVGO 。
另外,因为 SVG 是文本文件,所以可以使用 GZIP 压缩。
对于 SVG 我所知甚少,也就知道这些了。
优缺点
- 优点: 矢量图。
- 缺点: 渲染成本比较高; 不适合复杂的图像。
响应式图片
如今手机屏幕的像素密度越来越高,各种设备的屏幕尺寸差别越来越大,我们需要:
- 在不同尺寸的屏幕显示不同的图片;
- 对于屏幕密度高的屏幕使用更清晰(尺寸更大)的图片。
srcset 和 sizes
先看看MDN 文档,如果看完文档还是有点懵逼,可以再看看这篇大神的博客。
总结下基础信息:
<img>
举个例子;
<img
width="100px"
src="./img/1.png"
srcset="./img/1.png 1x, ./img/2.png 2x, ./img/3.png 3x"
/>
复制代码
在 1x 的屏幕上显示 1.png; 在 2x 的屏幕上显示 2.png; 在 3x 的屏幕上显示 3.png。其中 nx 指的是 DPR -- 设备像素比 (Device Pixel Ratio)。
再来个例子:
<img src="./img/1-1.png"
width="30%"
sizes="(max-width: 500px) 100px, (max-width: 800px) 200px, (max-width: 1200px) 300px"
srcset="./img/1-1.png 100w, ./img/1-2.png 200w, ./img/1-3.png 300w, ./img/1-4.png 400w"
/>
复制代码
不知到如何描述,还是举例说明吧: 如果使用宽为 720px 普通 PC 浏览器(DPR=1)访问,满足 (max-width: 800px) 200px , 此时我们期望图片 CSS 尺寸为 200px,因为 DPR == 1,于是,浏览器显示一个 srcset 中 200 × 1 = 200w 的图。 如果使用 ipad(屏幕宽度 768px, DPR=2)访问,同样满足 (max-width: 800px) 200px , 同样会获得期望图片 css 尺寸 200px, 因为 DPR = 2,于是,显示一个 srcset 中 200 × 2 = 400w 的图。
<picture> 标签
<picture>
<source srcset="./img/2-3.png" media="(min-width: 800px)" />
<source srcset="./img/2-2.png" media="(min-width: 500px)" />
<img width="100px" srcset="./img/2-1.png" />
</picture>
复制代码
<source> 标签有 sizes 和 srcset 属性,以及例程中的 media 属性。
CSS Images
对于 CSS 中引用的图像,也可以使用响应式图片:
<style>
.img {
height: 100px;
width: 100px;
background-repeat: no-repeat;
background-size: cover;
/**下面是主角**/
background-image: image-set(
url('./img/1.png') 1x,
url('./img/2.png') 2x,
url('./img/3.png') 3x
);
background-image: -webkit-image-set(
url('./img/1.png') 1x,
url('./img/2.png') 2x,
url('./img/3.png') 3x
);
}
</style>
<div class="img"></div>
复制代码
主流的浏览器在 2013 年左右就开始就开始支持了,目前来讲兼容性还算可以,不过还需要写前缀。
其他
与图片相关的优化策略还有很多,下面简单列举一些,有机会再具体写:
- base64 , 对于小图标 base64 后,可以直接硬编码到 HTML 中,用来减少 HTTP 请求;不过 base64 后字符串体积更大,且更消耗性能,不适用大图片。
- 雪碧图 : 小图标的经典的解决方案,用来减少 HTTP 请求。不够灵活;图标越多越难维护。因为 Iconfont 和 SVG 相关技术的普及,雪碧图的使用越来越少。
- Iconfont : 矢量图标,不失真;易维护;可以用 CSS 像文本一样设置样式。
- SVG Sprite : 多色图标解决方案 (原理可以看SVG 基础)。
- 懒加载 : 可以减少数据消耗,减少并发请求,改善用户体验。相关实现有很多细节,可以单独研究一下。
- 预加载 : 使用
<link rel=preload>; 提高图片请求优先级。 - 缓存图片 : 利用 HTTP 缓存来缓存图片资源。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web 2.0 Architectures
Duane Nickull、Dion Hinchcliffe、James Governor / O'Reilly / 2009 / USD 34.99
The "Web 2.0" phenomena has become more pervasive than ever before. It is impacting the very fabric of our society and presents opportunities for those with knowledge. The individuals who understand t......一起来看看 《Web 2.0 Architectures》 这本书的介绍吧!