This is a research project to make Image CDN using wasm codecs from squoosh.
Main pain point is to make wasm codecs play ball with deno. Neither wasm-bindgen nor emscripten support deno at the moment. On top of this, squoosh relies on built-in image decoding via getImageData and deno doesn't have any canvas implementation yet, so we will have to use extra wasm library to decode images into RGBA first.
Oxipng is written in rust, so this is relatively easy.
import * as wasm from "./squoosh_oxipng_bg.wasm";
This no longer works in deno, you have to use the following:
const f = await Deno.open("codecs/oxipng/pkg/squoosh_oxipng_bg.wasm");
const buf = await Deno.readAll(f);
const wasmModule = new WebAssembly.Module(buf);
const importObject = { "./squoosh_oxipng_bg.js": { __wbindgen_throw } };
const wasmInstance = new WebAssembly.Instance(wasmModule, importObject);
const wasm = wasmInstance.exports;
You have to import __wbindgen_throw
js function explicitly into wasm module, not sure how it works implicitly in squoosh.
Be sure to --allow-read=codecs
for this to work.
ImageQuant uses emscripten, this is going to be a bit trickier.
Makefile changes to make js glue have proper es6 import:
--s EXPORT_ES6=1 \
To interface js and c strings emscripten uses TextDecoder('utf-16le')
, this is going to throw, deno does not support it at the moment (see PR).
Since imagequant doesn't work with strings, it is safe to just replace it with utf-8.
Next problem is that emscripten glue uses its own wasm loading mechanism, based on the environment (and it is not aware of deno, so it fallbacks to generic web behavior). We have to overload readBinary function to work around erroneous environment detection.
png is not in squoosh, but we need it to work around missing canvas. It is a rust library and can be built the same way ImageQuant was.
Launch server with:
deno run --allow-net --allow-read=codecs src/main.ts
Be sure to launch server from ICDeno root, otherwise deno won't find wasm modules (file reads in deno are relative to work dir).
Once the server is up use it like this:
http://server-address/fetch/http://image-adress.png?format=webp&q=75
For example, with default local server location:
http://localhost:3030/fetch/http://www.libpng.org/pub/png/PngSuite/basn4a08.png?format=webp&q=75