基于頂級編解碼器實現(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)提供高效的圖像編解碼能力。其設計來源于Squoosh,強調(diào)瀏覽器兼容性和模塊化。特點:
- 專注于瀏覽器和Web Worker,適合前端環(huán)境。
- 模塊化設計:支持多種圖像格式(如@jSquash/jpeg、@jSquash/png、@jSquash/webp等),按需引入。
- 無動態(tài)代碼執(zhí)行:可在嚴格環(huán)境中運行,如Cloudflare Workers。
而WASM優(yōu)勢:
- 接近原生代碼的執(zhí)行速度,適合計算密集型任務如圖像壓縮。
- 無需依賴特定運行時環(huán)境,瀏覽器即可運行。
- WASM運行在沙箱環(huá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這些前端構建工具。
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編碼為目標格式的二進制數(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 - 使用官方庫的 "相當好的圖像格式" 編解碼器
- @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,否則會導致無法生效:
export default defineConfig({
optimizeDeps: {
exclude: ["@jsquash/jpeg", "@jsquash/oxipng", "@jsquash/webp"]
}
})
到此這篇關于基于頂級編解碼器實現(xiàn)純前端高效圖片壓縮效果詳解的文章就介紹到這了,更多相關前端圖片壓縮內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
js實現(xiàn)異步循環(huán)實現(xiàn)代碼
這篇文章主要介紹了js實現(xiàn)異步循環(huán)實現(xiàn)代碼,需要的朋友可以參考下2016-02-02
JavaScript中Iterator迭代器接口和循環(huán)
這篇文章主要介紹了JavaScript中Iterator迭代器接口和循環(huán),迭代器是數(shù)據(jù)結構遍歷的一種機制迭代器主要是提供for...of使用,更多相關內(nèi)推需要的小伙伴可以參考下面文章內(nèi)容2022-06-06

