mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-16 10:39:53 +00:00
Add avif decoder binaries
This commit is contained in:
22
codecs/avif_dec/README.md
Normal file
22
codecs/avif_dec/README.md
Normal 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()`.
|
||||||
96
codecs/avif_dec/avif_dec.cpp
Normal file
96
codecs/avif_dec/avif_dec.cpp
Normal 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
13
codecs/avif_dec/avif_dec.d.ts
vendored
Normal 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;
|
||||||
|
|
||||||
22
codecs/avif_dec/avif_dec.js
Normal file
22
codecs/avif_dec/avif_dec.js
Normal file
File diff suppressed because one or more lines are too long
BIN
codecs/avif_dec/avif_dec.wasm
Normal file
BIN
codecs/avif_dec/avif_dec.wasm
Normal file
Binary file not shown.
84
codecs/avif_dec/build.sh
Executable file
84
codecs/avif_dec/build.sh
Executable 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 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||||
BIN
codecs/avif_dec/example.avif
Normal file
BIN
codecs/avif_dec/example.avif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.9 KiB |
24
codecs/avif_dec/example.html
Normal file
24
codecs/avif_dec/example.html
Normal 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
1147
codecs/avif_dec/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
codecs/avif_dec/package.json
Normal file
13
codecs/avif_dec/package.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user