Make WebP decoder use memory views (#145)

* Make WebP decoder use memory views

* Update webp_dec README

* Port quantizer to memory views as well
This commit is contained in:
Surma
2018-08-21 13:29:53 +01:00
committed by Jake Archibald
parent 8006a1a5e7
commit e3b1b08424
18 changed files with 194 additions and 276 deletions

View File

@@ -1,22 +1,10 @@
import { QuantizeOptions } from './quantizer';
import imagequant from '../../../codecs/imagequant/imagequant';
import imagequant, { QuantizerModule } from '../../../codecs/imagequant/imagequant';
// Using require() so TypeScript doesnt complain about this not being a module.
const wasmBinaryUrl = require('../../../codecs/imagequant/imagequant.wasm');
// API exposed by wasm module. Details in the codecs README.
interface ModuleAPI {
version(): number;
create_buffer(width: number, height: number): number;
destroy_buffer(pointer: number): void;
quantize(buffer: number, width: number, height: number, numColors: number, dither: number): void;
zx_quantize(buffer: number, width: number, height: number, dither: number): void;
free_result(): void;
get_result_pointer(): number;
}
export default class ImageQuant {
private emscriptenModule: Promise<EmscriptenWasm.Module>;
private api: Promise<ModuleAPI>;
private emscriptenModule: Promise<QuantizerModule>;
constructor() {
this.emscriptenModule = new Promise((resolve) => {
@@ -41,45 +29,18 @@ export default class ImageQuant {
},
});
});
this.api = (async () => {
// Not sure why, but TypeScript complains that I am using
// `emscriptenModule` before its getting assigned, which is clearly not
// true :shrug: Using `any`
const m = await (this as any).emscriptenModule;
return {
version: m.cwrap('version', 'number', []),
create_buffer: m.cwrap('create_buffer', 'number', ['number', 'number']),
destroy_buffer: m.cwrap('destroy_buffer', '', ['number']),
quantize: m.cwrap('quantize', '', ['number', 'number', 'number', 'number', 'number']),
zx_quantize: m.cwrap('zx_quantize', '', ['number', 'number', 'number', 'number']),
free_result: m.cwrap('free_result', '', []),
get_result_pointer: m.cwrap('get_result_pointer', 'number', []),
};
})();
}
async quantize(data: ImageData, opts: QuantizeOptions): Promise<ImageData> {
const m = await this.emscriptenModule;
const api = await this.api;
const p = api.create_buffer(data.width, data.height);
m.HEAP8.set(new Uint8Array(data.data), p);
if (opts.zx) {
api.zx_quantize(p, data.width, data.height, opts.dither);
} else {
api.quantize(p, data.width, data.height, opts.maxNumColors, opts.dither);
}
const resultPointer = api.get_result_pointer();
const resultView = new Uint8Array(
m.HEAP8.buffer,
resultPointer,
data.width * data.height * 4,
);
const result = new Uint8ClampedArray(resultView);
api.free_result();
api.destroy_buffer(p);
const result = opts.zx ?
m.zx_quantize(data.data, data.width, data.height, opts.dither)
:
m.quantize(data.data, data.width, data.height, opts.maxNumColors, opts.dither);
return new ImageData(result, data.width, data.height);
m.free_result();
return new ImageData(new Uint8ClampedArray(result.buffer), result.width, result.height);
}
}