BIN
codecs/example.webp
Normal file
BIN
codecs/example.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
2
codecs/webp_dec/.gitignore
vendored
Normal file
2
codecs/webp_dec/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/*.wasm
|
||||
/*.js
|
42
codecs/webp_dec/README.md
Normal file
42
codecs/webp_dec/README.md
Normal file
@ -0,0 +1,42 @@
|
||||
# WebP decoder
|
||||
|
||||
- Source: <https://github.com/webmproject/libwebp>
|
||||
- Version: v0.6.1
|
||||
|
||||
## Example
|
||||
|
||||
See `example.html`
|
||||
|
||||
## API
|
||||
|
||||
### `int version()`
|
||||
|
||||
Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c
|
||||
|
||||
### `uint8_t* create_buffer(int size)`
|
||||
|
||||
Allocates an buffer for the file data.
|
||||
|
||||
### `void destroy_buffer(uint8_t* p)`
|
||||
|
||||
Frees a buffer created with `create_buffer`.
|
||||
|
||||
### `void decode(uint8_t* img_in, int size)`
|
||||
|
||||
Decodes the given webp file into raw RGBA. The result is implicitly stored and can be accessed using the `get_result_*()` functions.
|
||||
|
||||
### `void free_result()`
|
||||
|
||||
Frees the result created by `decode()`.
|
||||
|
||||
### `int get_result_pointer()`
|
||||
|
||||
Returns the pointer to the start of the buffer holding the encoded data. Length is width x height x 4 bytes.
|
||||
|
||||
### `int get_result_width()`
|
||||
|
||||
Returns the width of the image.
|
||||
|
||||
### `int get_result_height()`
|
||||
|
||||
Returns the height of the image.
|
44
codecs/webp_dec/example.html
Normal file
44
codecs/webp_dec/example.html
Normal file
@ -0,0 +1,44 @@
|
||||
<!doctype html>
|
||||
<script src='webp_dec.js'></script>
|
||||
<script>
|
||||
const Module = webp_dec();
|
||||
|
||||
async function loadFile(src) {
|
||||
const resp = await fetch(src);
|
||||
return await resp.arrayBuffer();
|
||||
}
|
||||
|
||||
Module.onRuntimeInitialized = async _ => {
|
||||
const api = {
|
||||
version: Module.cwrap('version', 'number', []),
|
||||
create_buffer: Module.cwrap('create_buffer', 'number', ['number', 'number']),
|
||||
destroy_buffer: Module.cwrap('destroy_buffer', '', ['number']),
|
||||
decode: Module.cwrap('decode', '', ['number', 'number']),
|
||||
free_result: Module.cwrap('free_result', '', ['number']),
|
||||
get_result_pointer: Module.cwrap('get_result_pointer', 'number', []),
|
||||
get_result_width: Module.cwrap('get_result_width', 'number', []),
|
||||
get_result_height: Module.cwrap('get_result_height', 'number', []),
|
||||
};
|
||||
const image = await loadFile('../example.webp');
|
||||
const p = api.create_buffer(image.byteLength);
|
||||
Module.HEAP8.set(new Uint8Array(image), p);
|
||||
api.decode(p, image.byteLength);
|
||||
const resultPointer = api.get_result_pointer();
|
||||
if(resultPointer === 0) {
|
||||
throw new Error("Could not decode image");
|
||||
}
|
||||
const resultWidth = api.get_result_width();
|
||||
const resultHeight = api.get_result_height();
|
||||
const resultView = new Uint8Array(Module.HEAP8.buffer, resultPointer, resultWidth * resultHeight * 4);
|
||||
const result = new Uint8ClampedArray(resultView);
|
||||
const imageData = new ImageData(result, resultWidth, resultHeight);
|
||||
api.free_result(resultPointer);
|
||||
api.destroy_buffer(p);
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = resultWidth;
|
||||
canvas.height = resultHeight;
|
||||
document.body.appendChild(canvas);
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
};
|
||||
</script>
|
1147
codecs/webp_dec/package-lock.json
generated
Normal file
1147
codecs/webp_dec/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
codecs/webp_dec/package.json
Normal file
13
codecs/webp_dec/package.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "webp_dec",
|
||||
"scripts": {
|
||||
"install": "napa",
|
||||
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc -O3 -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]' -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"webp_dec\"' -I node_modules/libwebp -o ./webp_dec.js webp_dec.c node_modules/libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c"
|
||||
},
|
||||
"napa": {
|
||||
"libwebp": "webmproject/libwebp#v0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"napa": "^3.0.0"
|
||||
}
|
||||
}
|
51
codecs/webp_dec/webp_dec.c
Normal file
51
codecs/webp_dec/webp_dec.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include "emscripten.h"
|
||||
#include "src/webp/decode.h"
|
||||
#include "src/webp/demux.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int version() {
|
||||
return WebPGetDecoderVersion();
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
uint8_t* create_buffer(int size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void destroy_buffer(uint8_t* p) {
|
||||
free(p);
|
||||
}
|
||||
|
||||
int result[3];
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void decode(uint8_t* img_in, int size) {
|
||||
int width, height;
|
||||
uint8_t* img_out = WebPDecodeRGBA(img_in, size, &width, &height);
|
||||
result[0] = (int)img_out;
|
||||
result[1] = width;
|
||||
result[2] = height;
|
||||
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void free_result() {
|
||||
WebPFree(result[0]);
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int get_result_pointer() {
|
||||
return result[0];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int get_result_width() {
|
||||
return result[1];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int get_result_height() {
|
||||
return result[2];
|
||||
}
|
||||
|
@ -38,7 +38,7 @@
|
||||
api.free_result(resultPointer);
|
||||
api.destroy_buffer(p);
|
||||
|
||||
const blob = new Blob([result], {type: 'image/jpeg'});
|
||||
const blob = new Blob([result], {type: 'image/webp'});
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
const img = document.createElement('img');
|
||||
img.src = blobURL;
|
||||
|
Reference in New Issue
Block a user