WebAssembly MozJPEG encoder.
Inspired by cyrilwanner/wasm-codecs, saschazar21/webassembly/mozjpeg and the thirst for adventures.
- 321 KiB before gzip (wasm + js), 34 KiB after;
- TypeScript definitions;
- node and browser support;
- different input color spaces;
grayscale
,RGB
,YCbCr
,CMYK
andYCCK
output color spaces (not all in->out transformations supported, see mozjpeg/libjpeg.txt);- disabled arithmetic coding (smaller bundle);
- sequential (aka "bump") memory allocator (smaller bundle, +30% memory usage);
- no build-in worker.
npm install https://github.com/3bl3gamer/wasm-mozjpeg
import { loadWebModule, compressSimpleRGBA } from 'wasm-mozjpeg'
loadWebModule().then(mozJpeg => {
const quality = 75
const iData = someCanvas.getContext('2d').getImageData(0, 0, 320, 240)
const jpegChunks = compressSimpleRGBA(mozJpeg, iData.width, iData.height, quality, iData.data)
const blob = new Blob(jpegChunks, { type: 'image/jpeg' })
const img = new Image()
img.src = URL.createObjectURL(blob)
document.body.appendChild(img)
})
import { loadWebModule, initCompressSimple, writeRowsSimple,
JCS_EXT_RGBA, JCS_YCbCr } from 'wasm-mozjpeg'
loadWebModule().then(mozJpeg => {
const iData = someCanvas.getContext('2d').getImageData(0, 0, 320, 240)
const channels = 4 //R, G, B and A
let { rowBufLocation, imgChunks } =
initCompressSimple(mozJpeg, iData.width, iData.height, JCS_EXT_RGBA, channels)
mozJpeg.cinfo_set_out_color_space(JCS_YCbCr)
mozJpeg.cinfo_set_quant_table(3)
mozJpeg.cinfo_set_quality(95, -1)
mozJpeg.cinfo_set_optimize_coding(true)
mozJpeg.cinfo_set_chroma_subsample(2, 2)
mozJpeg.cinfo_set_smoothing_factor(0)
mozJpeg.cinfo_disable_progression()
mozJpeg.cinfo_set_trellis(10, true, true, true)
mozJpeg.start_compress()
writeRowsSimple(mozJpeg, rowBufLocation, iData.data, iData.height, iData.width * channels)
mozJpeg.finish_compress()
const blob = new Blob(imgChunks, { type: 'image/jpeg' })
const img = new Image()
img.src = URL.createObjectURL(blob)
document.body.appendChild(img)
})
Different in/out color spaces may be used (see features). Just ensure MozJPEG can handle required color transformation.
For example, if input color data is already in YCbCr
, it may be encoded directly:
// buffer should have length = width * wheight * 3
const { widht, height, buffer } = getYCbCrPixels()
const channels = 3
let { rowBufLocation, imgChunks } =
initCompressSimple(mozJpeg, width, height, JCS_YCbCr, channels)
mozJpeg.cinfo_set_out_color_space(JCS_YCbCr)
//...
mozJpeg.start_compress()
writeRowsSimple(mozJpeg, rowBufLocation, buffer, height, width * channels)
mozJpeg.finish_compress()
//...
More info in index.d.ts, mozjpeg/libjpeg.txt and mozjpeg/README-mozilla.txt.
./build_wasm.sh
— rebuilds mozjpeg.wasm
, generates const.js
, requires Emscripten
.
./generate_types.sh
— generates .d.ts
files by JSDoc
annotations.