Add avif decoder binaries

This commit is contained in:
Surma
2020-02-05 16:35:10 -08:00
committed by Ingvar Stepanyan
parent d0f5d5a644
commit 34cb55978f
10 changed files with 1421 additions and 0 deletions

22
codecs/avif_dec/README.md Normal file
View File

@ -0,0 +1,22 @@
# WebP decoder
- Source: <https://github.com/webmproject/libwebp>
- Version: v1.0.2
## Example
See `example.html`
## API
### `int version()`
Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c
### `RawImage decode(std::string buffer)`
Decodes the given webp buffer into raw RGBA. `RawImage` is a class with 3 fields: `buffer`, `width`, and `height`.
### `void free_result()`
Frees the result created by `decode()`.

View File

@ -0,0 +1,96 @@
#include "avif/avif.h"
#include <emscripten/bind.h>
#include <emscripten/val.h>
using namespace emscripten;
class RawImage {
public:
val buffer;
int width;
int height;
RawImage(val b, int w, int h) : buffer(b), width(w), height(h) {}
};
// NOTE: avifDecoderRead() offers the simplest means to get an avifImage that is
// complete independent of an avifDecoder, but at the cost of additional
// allocations and copies, and no support for image sequences. If you don't mind
// keeping around the avifDecoder while you read in the image and/or need image
// sequence support, skip ahead to the Advanced Decoding example. It is only one
// additional function call, and the avifImage is owned by the avifDecoder.
uint8_t *result;
RawImage decode(std::string avifimage) {
// point raw.data and raw.size to the contents of an .avif(s)
avifROData raw;
raw.data = (uint8_t *)avifimage.c_str();
raw.size = avifimage.length();
avifImage *image = avifImageCreateEmpty();
avifDecoder *decoder = avifDecoderCreate();
avifResult decodeResult = avifDecoderRead(decoder, image, &raw);
if (decodeResult != AVIF_RESULT_OK) {
return RawImage(val::null(), -1, -1);
// printf("ERROR: Failed to decode: %s\n", avifResultToString(result));
}
int width = image->width;
int height = image->height;
int numBytes = width * height * 4;
result = new uint8_t[numBytes];
// image is an independent copy of decoded data, decoder may be destroyed here
// ... image->width;
// ... image->height;
// ... image->depth; // If >8, all plane ptrs below are uint16_t*
// ... image->yuvFormat; // U and V planes might be smaller than Y based on
// format, use avifGetPixelFormatInfo() to find out in a generic way
// Option 1: Use YUV planes directly
// ... image->yuvPlanes;
// ... image->yuvRowBytes;
// Option 2: Convert to RGB and use RGB planes
avifImageYUVToRGB(image);
// ... image->rgbPlanes;
// ... image->rgbRowBytes;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixelOffset = y * image->width + x;
result[pixelOffset * 4 + 0] = image->rgbPlanes[0][pixelOffset];
result[pixelOffset * 4 + 1] = image->rgbPlanes[1][pixelOffset];
result[pixelOffset * 4 + 2] = image->rgbPlanes[2][pixelOffset];
if (image->alphaPlane) {
result[pixelOffset * 4 + 3] = image->alphaPlane[pixelOffset];
} else {
result[pixelOffset * 4 + 3] = 255;
}
}
}
// // Use alpha plane, if present
// if (image->alphaPlane) {
// ... image->alphaPlane;
// ... image->alphaRowBytes;
// }
avifImageDestroy(image);
avifDecoderDestroy(decoder);
return RawImage(val(typed_memory_view(numBytes, result)), (int)width,
(int)height);
}
void free_result() { delete result; }
EMSCRIPTEN_BINDINGS(my_module) {
class_<RawImage>("RawImage")
.property("buffer", &RawImage::buffer)
.property("width", &RawImage::width)
.property("height", &RawImage::height);
function("decode", &decode);
function("free_result", &free_result);
}

13
codecs/avif_dec/avif_dec.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
interface RawImage {
buffer: Uint8Array;
width: number;
height: number;
}
interface WebPModule extends EmscriptenWasm.Module {
decode(data: BufferSource): RawImage;
free_result(): void;
}
export default function(opts: EmscriptenWasm.ModuleOpts): WebPModule;

File diff suppressed because one or more lines are too long

Binary file not shown.

84
codecs/avif_dec/build.sh Executable file
View File

@ -0,0 +1,84 @@
#!/bin/bash
set -e
export OPTIMIZE="-Os"
export LDFLAGS="${OPTIMIZE}"
export CFLAGS="${OPTIMIZE}"
export CPPFLAGS="${OPTIMIZE}"
echo "============================================="
echo "Compiling libaom"
echo "============================================="
(
cd node_modules/libavif/ext
test -d aom || git clone -b v1.0.0-errata1-avif --depth 1 https://aomedia.googlesource.com/aom aom
cd aom
mkdir -p build.libavif
cd build.libavif
emcmake cmake \
-DCMAKE_BUILD_TYPE=Release \
-DENABLE_CCACHE=0 \
-DAOM_TARGET_CPU=generic \
-DENABLE_DOCS=0 \
-DENABLE_TESTS=0 \
-DCONFIG_ACCOUNTING=1 \
-DCONFIG_INSPECTION=0 \
-DCONFIG_MULTITHREAD=0 \
-DCONFIG_RUNTIME_CPU_DETECT=0 \
-DCONFIG_WEBM_IO=0 \
../
emmake make
)
echo "============================================="
echo "Compiling libaom done"
echo "============================================="
echo "============================================="
echo "Compiling libavif"
echo "============================================="
(
cd node_modules/libavif
mkdir -p build
cd build
emcmake cmake \
DCMAKE_BUILD_TYPE=Release \
-DAVIF_CODEC_AOM=1 \
-DAVIF_LOCAL_AOM=1 \
../
emmake make
)
echo "============================================="
echo "Compiling libavif done"
echo "============================================="
echo "============================================="
echo "Compiling wasm bindings"
echo "============================================="
(
emcc \
${OPTIMIZE} \
--bind \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s 'EXPORT_NAME="avif_dec"' \
--std=c++11 \
-I ./node_modules/libavif/include \
-o ./avif_dec.js \
-x c++ \
avif_dec.cpp \
./node_modules/libavif/build/libavif.a \
./node_modules/libavif/ext/aom/build.libavif/libaom.a
)
echo "============================================="
echo "Compiling wasm bindings done"
echo "============================================="
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
echo "Did you update your docker image?"
echo "Run \`docker pull trzeci/emscripten\`"
echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

View File

@ -0,0 +1,24 @@
<!doctype html>
<script src='avif_dec.js'></script>
<script>
const Module = avif_dec();
async function loadFile(src) {
const resp = await fetch(src);
return await resp.arrayBuffer();
}
Module.onRuntimeInitialized = async _ => {
const image = await loadFile('../example.avif');
const result = Module.decode(image);
console.log(result.width, result.height, result.buffer);
const imageData = new ImageData(new Uint8ClampedArray(result.buffer), result.width, result.height);
Module.free_result();
const canvas = document.createElement('canvas');
canvas.width = result.width;
canvas.height = result.height;
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
ctx.putImageData(imageData, 0, 0);
};
</script>

1147
codecs/avif_dec/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
{
"name": "avif_dec",
"scripts": {
"install": "napa",
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten ./build.sh"
},
"napa": {
"libavif": "AOMediaCodec/libavif#v0.5.4"
},
"devDependencies": {
"napa": "3.0.0"
}
}