前端常說的優化之圖片優化

首先要說的是,關於圖片的編碼原理,壓縮算法這些都是很專業的領域,做爲一個小前端來說,知道通常的應用場景和通常的特性就能夠了。css

基本概念

矢量圖與柵格圖像

  • 矢量圖:形使用線、點和多邊形來表示圖像。
  • 柵格圖像: 經過對矩形格柵內的每一個像素的值進行編碼來表示圖像。

矢量圖: 前端最多見的矢量圖是 SVG。關於 SVG 能夠看 SVG 基礎 這篇文章,SVG 適用於包含簡單的幾何圖形的圖像,由於 SVG 縮放不失真,因此 SVG 最適合用於高分辨率屏幕和須要以不一樣尺寸顯示的圖像。前端

柵格圖像:git

  • 由一個個的像素柵格組成;
  • 每一個像素都編碼了顏色和透明度信息;
  • 使用不用的壓縮算法(不一樣的圖片格式),以減少圖像的文件大小。

由於源數據太大,通常在網頁中使用的是通過壓縮的文件,下面是一個 JPG 文件的壓縮和解壓的過程:github

jpg 編碼與解碼

這裏涉及兩個過程:web

  • 編碼: 源數據編碼獲得 JPG 文件;這個 JPG 文件,用於存儲和出傳輸。
  • 解碼: 要顯示這個圖像的時候,解碼 JPG 文件內容獲得源數據。

有損壓縮無損壓縮

繼續以上面的 JPG 編解碼爲例。源數據是2 維「像素」柵格,好比,一個 10 × 10 的圖像便有 100 個像素。每一個像素又存儲了 RGBA 的值: (R) 紅色通道、(G) 綠色通道、(B) 藍色通道和 (A) alpha(透明度)通道。每一個通道 8 位,即每一個像素 4 個字節。 瀏覽器在拿到 jpg 文件以後,解碼獲得一個同原始數據同樣的像素柵格序列,也要爲每一個像素分配 4 個字節的內存(不管使用什麼格式傳輸,最後還原數據會和原始數據同樣大)。算法

那麼, 若是瀏覽器能夠解碼獲得原始數據,則爲無損壓縮。若是爲了獲得更小的文件,壓縮過程當中丟棄了一些信息,並且這個過程是不可逆的,那麼瀏覽器解碼也就沒法獲得原始數據,這種壓縮方式即是有損壓縮chrome

對於柵格圖像要根據不一樣的使用場景選擇合適格式,接下來探究一些常見的這幾種圖片格式。後端

常見圖片格式

JPG/JPEG

多是目前世界上使用最普遍的圖像格式,特色:瀏覽器

  • 不支持透明;
  • 有損壓縮。

JPEG 適合於色彩豐富,線條感比較弱的圖片,好比大的背景圖,banner 圖等等。JPEG 是有損壓縮(也有無損的 JPEG,支持不夠普遍),壓縮時質量級別越低體積越小,圖片也越模糊。因此,在使用時,須要根據須要選擇合適的質量級別。緩存

優化

JPEG 有多種不一樣的壓縮模式, 好比常見的基線(順序)JPEG 和漸進式 JPEG (PJPEG)。

基線 JPEG(大多數圖像編輯和優化工具的默認設置)以相對簡單的方式進行編碼和解碼:從上到下。 在鏈接速度緩慢或不穩定的狀況下加載基線 JPEG 時,用戶會先看到圖像的頂部,而後隨着圖像加載逐漸看到圖像的其餘部分。 盜用谷歌圖:

jpg baseline

基線 JPEG 的加載方式是從上到下,而漸進式 JPEG 是從模糊到清晰。

漸進式 JPEG 將圖像分紅屢次掃描, 第一次掃描以模糊或低質量設置顯示圖像,後續掃描逐步提升圖像質量。 咱們能夠將這個過程看做「漸進式」提升圖像質量。 每次「掃描」圖像都會增長細節的清晰程度,最後合併爲全畫質圖像。

jpg progressive

漸進式 JPEG 能夠在沒有下載完圖片就能夠看到最終圖像的大體輪廓,必定程度上能夠提高用戶體驗。

與基線 JPEG 相比,漸進式 JPEG:

  • 比較大的圖,有更高壓縮率;
  • 須要更多的 CPU 資源去解碼。

使用基線 JPEG 相比仍是漸進式 JPEG,須要咱們根據場景選擇,在文件大小,網絡延遲和 CPU 消耗之間作一個權衡。


關於漸進式 JPEG 扯點別的: 漸進式 JPEG 採用的掃描算法有個學名 -- 隔行掃描,更多信息請看 維基百科 的介紹。

隔行掃描的效果是下面這樣的,感受這張圖專業並且很形象:

Interlacing

除了 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 會比其餘格式的圖都會小,好比: 這樣一張二維碼:

png-qrcode

由於,二維碼只有黑色和白色,因此把調色板的顏色數量設爲 2, 導出 256 × 256 的圖(單位:像素):

  • PNG8: 2.457KB
  • GIF: 3.402KB

導出爲 50 × 50 的圖:

  • PNG8: 648B
  • GIF: 425B

GIF 以下,還能夠掃碼:

gif-qrcode

而當導出更小的圖時, 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-caniuse

從圖中能夠看到舊瀏覽器和蘋果家的產品基本不支持。

優化

關於 WebP 的優化,基本就是解決兼容問題。

嗅探

查看瀏覽器支不支持,最簡單的方法就是給 img 元素一個 .webp 的圖像(通常使用 1×1px 大小 webp 的 base64 字符串),看看是否能正常加載。基本原理以下:

var image = new Image();
image.onload = function() {
    // 支持
};

image.error = function() {
    // 不支持
};
image.src = 'data:image/webp;base64,xxxxx';
複製代碼

好比淘寶就在使用相似的技術,

webp-caniuse

<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 文檔,若是看完文檔仍是有點懵逼,能夠再看看這篇大神的博客

總結下基礎信息:

  • srcset 和 sizes 是 <img> 元素的屬性;
  • srcset: 定義了一個供瀏覽器選擇的圖像集合;
  • sizes: 必須結合 srcset 屬性使用;其值也是一組值,經過不一樣的媒體條件,指出最合適的圖片;
  • 當 srcset 使用像素密度描述符時,無需 sizes;

舉個例子;

<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 年左右就開始就開始支持了,目前來說兼容性還算能夠,不過還須要寫前綴。

其餘

與圖片相關的優化策略還有不少,下面簡單列舉一些,有機會再具體寫:

  1. base64, 對於小圖標 base64 後,能夠直接硬編碼到 HTML 中,用來減小 HTTP 請求;不過 base64 後字符串體積更大,且更消耗性能,不適用大圖片。
  2. 雪碧圖: 小圖標的經典的解決方案,用來減小 HTTP 請求。不夠靈活;圖標越多越難維護。由於 Iconfont 和 SVG 相關技術的普及,雪碧圖的使用愈來愈少。
  3. Iconfont: 矢量圖標,不失真;易維護;能夠用 CSS 像文本同樣設置樣式。
  4. SVG Sprite: 多色圖標解決方案 (原理能夠看SVG 基礎)。
  5. 懶加載: 能夠減小數據消耗,減小併發請求,改善用戶體驗。相關實現有不少細節,能夠單獨研究一下。
  6. 預加載: 使用 <link rel=preload>; 提升圖片請求優先級。
  7. 緩存圖片: 利用 HTTP 緩存來緩存圖片資源。

最後

沒有萬能的優化策略,根據使用場景選擇最合適的優化便可:

  • 能不使用圖片就不使用,好比能夠用 CSS 和 Iconfont 代替。
  • 適合用矢量圖,就用矢量圖。
  • 儘可能使用小尺寸圖片。
  • 大圖儘可能不使用 PNG24 / PNG32。
  • 能用 PNG8 就不用 PNG24 / PNG32。
  • 能用 WebP 就用 WebP。
  • 非動畫場景不使用 GIF。
  • ......
相關文章
相關標籤/搜索