基于頂級編解碼器實現(xiàn)純前端高效圖片壓縮效果詳解
Google的Squoosh項目封裝了MozJPEG、libwebp、rust Oxipng等頂級圖像編解碼器,但是使用依賴于Node.js,而jSquash項目對此進行了二次封裝,將底層編解碼器以WebAssembly的形式提供,實現(xiàn)不依賴node的純前端的壓縮方式。
經(jīng)測試可以將10mb的png壓縮為500kb的jpg,肉眼畫質(zhì)無損失,95%的優(yōu)化。
jSquash
jSquash是一個輕量級、基于WebAssembly(WASM)的圖像處理庫,旨在為瀏覽器和V8運行時(如Cloudflare Workers)提供高效的圖像編解碼能力。其設(shè)計來源于Squoosh,強調(diào)瀏覽器兼容性和模塊化。特點:
- 專注于瀏覽器和Web Worker,適合前端環(huán)境。
- 模塊化設(shè)計:支持多種圖像格式(如@jSquash/jpeg、@jSquash/png、@jSquash/webp等),按需引入。
- 無動態(tài)代碼執(zhí)行:可在嚴(yán)格環(huán)境中運行,如Cloudflare Workers。
而WASM優(yōu)勢:
- 接近原生代碼的執(zhí)行速度,適合計算密集型任務(wù)如圖像壓縮。
- 無需依賴特定運行時環(huán)境,瀏覽器即可運行。
- WASM運行在沙箱環(huán)境中,適合嚴(yán)格的執(zhí)行環(huán)境。
比如@jSquash/jpeg使用MozJPEG庫進行JPEG圖像的編解碼,@jSquash/webp基于libwebp實現(xiàn)WebP格式支持。通過Emscripten編譯為WASM模塊,并通過JavaScript接口 暴露給開發(fā)者。
jSquash采用ES Module(ESM)格式,所有模塊(如@jSquash/avif、@jSquash/png)均為獨立包,可按需引入,減少了打包體積,適合Vite、Webpack這些前端構(gòu)建工具。
jSquash也支持通過CDN直接使用(大陸環(huán)境不穩(wěn)定):
import { decode } from 'https://unpkg.com/@jsquash/jpeg?module';
處理流程
- 解碼(Decode):將輸入的圖像二進制數(shù)據(jù)(ArrayBuffer)解碼為原始RGB圖像數(shù)據(jù)(ImageData)。例如,@jSquash/jpeg的decode方法將JPEG文件轉(zhuǎn)換為ImageData對象。
- 處理(可選):支持調(diào)整大小(@jSquash/resize)或優(yōu)化(如@jSquash/oxipng)。調(diào)整大小支持多種算法(如Lanczos3、Magic Kernel)。
- 編碼(Encode):將處理后的ImageData編碼為目標(biāo)格式的二進制數(shù)據(jù)。例如,@jSquash/webp的encode方法生成WebP格式的ArrayBuffer。
jSquash的WASM模塊通常由生成的膠水代碼(glue code)自動初始化,支持大多數(shù)Web打包工具
圖像格式支持
每種格式由獨立的模塊實現(xiàn):
- @jSquash/avif - 使用 libavif 庫的 AVIF 圖像編碼器和解碼器
- @jSquash/jpeg - 使用 MozJPEG 庫的 JPEG 圖像編碼器和解碼器
- @jSquash/jxl - 使用 libjxl 庫的 JPEG XL 圖像編碼器和解碼器
- @jSquash/oxipng - 使用 Oxipng 的 PNG 圖像優(yōu)化器
- @jSquash/png - 使用 rust PNG crate 的 PNG 圖像編解碼器
- @jSquash/qoi - 使用官方庫的 "相當(dāng)好的圖像格式" 編解碼器
- @jSquash/resize - 使用 rust resize、hqx 和 magic-kernel 庫的圖像縮放工具。支持降縮和升縮。
- @jSquash/webp - 使用 libwebp 的 WebP 圖像編碼器和解碼器
完整見官方readme,按需npm install即可(install的是@jsquash/xx而不是@jSquash/xx,要小寫)。
代碼
只包括圖像處理的核心部分,圖像是上傳還是直接讀取本地自行處理。
注意每個模塊的使用方式是不一樣的,比如oxipng的輸入類型為arrayBuffer,而MozJpeg為imageData,具體需要查看每個封裝模塊的readme。
jpeg、webp:這里encode可以傳入配置quality,默認為75(0-100),具體庫配置不同。png配置為level(1-6)
import { decode } from '@jsquash/jpeg'; import { encode } from '@jsquash/webp'; async function convertToWebP(url) { try { const response = await fetch(url); const imageBuffer = await response.arrayBuffer(); // 或者直接處理blob對象 // file.arrayBuffer() const imageData = await decode(imageBuffer); // 這里encode可以傳入配置{ quality },默認為75(0-100),具體庫配置不同。png配置為level(1-6) const webpBuffer = await encode(imageData); const blob = new Blob([webpBuffer], { type: 'image/webp' }); return URL.createObjectURL(blob); } catch (error) { console.error('轉(zhuǎn)換失敗:', error); } }
rust oxipng:
這里用canvas解碼,因為這個庫沒提供解碼函數(shù)。
const bitmap = await createImageBitmap(file); const canvas = new OffscreenCanvas(bitmap.width, bitmap.height); const ctx = canvas.getContext('2d'); ctx.drawImage(bitmap, 0, 0); const imageData = ctx.getImageData(0, 0, bitmap.width, bitmap.height); bitmap.close(); return imageData;
編碼:
import {optimise as encodePNG} from '@jsquash/oxipng'; let buffer = await encodePNG(buffer, { level: 2 }), return new Blob([buffer], {type: 'image/png'});
沒有明確要求(比如png保留透明通道)的話建議輸出格式轉(zhuǎn)為jpeg,能大幅度減小體積。
注意
vite優(yōu)化的時候要避開這些庫,不能影響wasm,否則會導(dǎo)致無法生效:
export default defineConfig({ optimizeDeps: { exclude: ["@jsquash/jpeg", "@jsquash/oxipng", "@jsquash/webp"] } })
到此這篇關(guān)于基于頂級編解碼器實現(xiàn)純前端高效圖片壓縮效果詳解的文章就介紹到這了,更多相關(guān)前端圖片壓縮內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Bootstrap Table實現(xiàn)定時刷新數(shù)據(jù)的方法
這篇文章主要介紹了Bootstrap Table實現(xiàn)定時刷新數(shù)據(jù)的方法,在這里小編比較推薦使用第二種方法,需要的朋友參考下吧2018-08-08JS+CSS實現(xiàn)淡入式焦點圖片幻燈切換效果的方法
這篇文章主要介紹了JS+CSS實現(xiàn)淡入式焦點圖片幻燈切換效果的方法,實例分析了javascript操作圖片、css等元素實現(xiàn)幻燈片的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-02-02ElementUI 的 Tree 組件的基本使用實戰(zhàn)教程
這篇文章主要介紹了ElementUI 的 Tree 組件的基本使用實戰(zhàn)教程,本文結(jié)合示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-12-12javascript獲取checkbox復(fù)選框獲取選中的選項
這篇文章主要介紹了javascript獲取checkbox復(fù)選框獲取選中的選項的方法,需要的朋友可以參考下2014-08-08Javascript實現(xiàn)獲取及設(shè)置光標(biāo)位置的方法
這篇文章主要介紹了Javascript實現(xiàn)獲取及設(shè)置光標(biāo)位置的方法,涉及javascript針對頁面光標(biāo)位置的相關(guān)操作技巧,具有良好的兼容性,非常簡單實用,需要的朋友可以參考下2015-07-07