ソースコード
動作デモ
動機
写真を扱うスマホアプリをCordovaで作っていて、写真のアップロードに時間がかかる問題を解決したかった。
サーバーに送ってから処理するのではなく、ブラウザ側で処理したい。
画像のリサイズはすでにcanvasを使って行っている。
画像のファイルサイズをmozJPEGで最適化することで、より軽量にして、アップロードの高速化、表示の高速化したい。
開発
viteを使っています。
https://vitejs.dev/
npm install
npm start
使ったライブラリ
@wasm-codecs/mozjpeg
https://github.com/cyrilwanner/wasm-codecs/tree/master/packages/mozjpeg
このWebAssemblyを使う。
サンプルはnode。このままではブラウザ上では動かない。
WebAssemblyに入力するimageは、raw image。
CanvasのgetImageDataで得ることができる。
const image = ctx.getImageData(0, 0, img.width, img.height)
const encodedImage = await encode(image.data.buffer, {
width: image.width,
height: image.height,
channels: 4
}, {
quality: 80,
colorSpace: 3
});
トラブルシューティング
encodeを実行すると
Uncaught ReferenceError: buffer is not defined
というエラーが出るので、
<script src="https://bundle.run/buffer"></script>
公開されているbufferライブラリをindex.htmlに追加した。
ポイント
publicディレクトリに、wasmファイルを置いて、url直下でアクセスできるようにした。
mozjpegのwasmファイルは、node_modulesの@wasm-codecs/mozjpegの中からコピー。
/public
mozjpeg.wasm
結論
結論的には、
ctx.canvas.toDataURL('image/jpeg', 0.8)
canvasからJPEG画像に変換するときに圧縮率を指定できるので、小さい画像ならmozJPEGで最適化しても大きな差は出ない。
数MBの画像をアップロードする場合は効果ありあそう。