mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-15 10:09:45 +00:00
Add AVIF encoder
This commit is contained in:
18
codecs/avif_enc/README.md
Normal file
18
codecs/avif_enc/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# AVIF encoder
|
||||||
|
|
||||||
|
- Source: <https://github.com/AOMediaCodec/libavif>
|
||||||
|
- Version: v0.5.4
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
Run example.js
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### `RawImage decode(std::string buffer)`
|
||||||
|
|
||||||
|
Decodes the given avif buffer into raw RGBA. `RawImage` is a class with 3 fields: `buffer`, `width`, and `height`.
|
||||||
|
|
||||||
|
### `void free_result()`
|
||||||
|
|
||||||
|
Frees the result created by `decode()`.
|
||||||
49
codecs/avif_enc/avif_enc.cpp
Normal file
49
codecs/avif_enc/avif_enc.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include "avif/avif.h"
|
||||||
|
#include <emscripten/bind.h>
|
||||||
|
#include <emscripten/val.h>
|
||||||
|
|
||||||
|
using namespace emscripten;
|
||||||
|
|
||||||
|
avifRWData output = AVIF_DATA_EMPTY;
|
||||||
|
val encode(std::string buffer, int width, int height) {
|
||||||
|
int depth = 8;
|
||||||
|
avifPixelFormat format = AVIF_PIXEL_FORMAT_YUV420;
|
||||||
|
avifImage *image = avifImageCreate(width, height, depth, format);
|
||||||
|
|
||||||
|
uint8_t *rgba = (uint8_t *)buffer.c_str();
|
||||||
|
|
||||||
|
avifImageAllocatePlanes(image, AVIF_PLANES_RGB);
|
||||||
|
avifImageAllocatePlanes(image, AVIF_PLANES_A);
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
int pixelOffset = y * width + x;
|
||||||
|
image->rgbPlanes[0][pixelOffset] = rgba[pixelOffset * 4 + 0];
|
||||||
|
image->rgbPlanes[1][pixelOffset] = rgba[pixelOffset * 4 + 1];
|
||||||
|
image->rgbPlanes[2][pixelOffset] = rgba[pixelOffset * 4 + 2];
|
||||||
|
image->alphaPlane[pixelOffset] = rgba[pixelOffset * 4 + 3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
avifEncoder *encoder = avifEncoderCreate();
|
||||||
|
encoder->maxThreads = 1;
|
||||||
|
encoder->minQuantizer = AVIF_QUANTIZER_LOSSLESS;
|
||||||
|
encoder->maxQuantizer = AVIF_QUANTIZER_LOSSLESS;
|
||||||
|
avifResult encodeResult = avifEncoderWrite(encoder, image, &output);
|
||||||
|
if (encodeResult != AVIF_RESULT_OK) {
|
||||||
|
return val::null();
|
||||||
|
}
|
||||||
|
// output contains a valid .avif file's contents
|
||||||
|
// ... output.data;
|
||||||
|
// ... output.size;
|
||||||
|
avifImageDestroy(image);
|
||||||
|
avifEncoderDestroy(encoder);
|
||||||
|
return val(typed_memory_view(output.size, output.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_result() { avifRWDataFree(&output); }
|
||||||
|
|
||||||
|
EMSCRIPTEN_BINDINGS(my_module) {
|
||||||
|
function("encode", &encode);
|
||||||
|
function("free_result", &free_result);
|
||||||
|
}
|
||||||
9
codecs/avif_enc/avif_enc.d.ts
vendored
Normal file
9
codecs/avif_enc/avif_enc.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
// import { EncodeOptions } from '../../src/codecs/webp/encoder-meta';
|
||||||
|
|
||||||
|
interface WebPModule extends EmscriptenWasm.Module {
|
||||||
|
encode(data: BufferSource, width: number, height: number): Uint8Array;
|
||||||
|
free_result(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default function(opts: EmscriptenWasm.ModuleOpts): WebPModule;
|
||||||
22
codecs/avif_enc/avif_enc.js
Normal file
22
codecs/avif_enc/avif_enc.js
Normal file
File diff suppressed because one or more lines are too long
BIN
codecs/avif_enc/avif_enc.wasm
Normal file
BIN
codecs/avif_enc/avif_enc.wasm
Normal file
Binary file not shown.
84
codecs/avif_enc/build.sh
Executable file
84
codecs/avif_enc/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 "============================================="
|
||||||
|
test -n "$SKIP_LIBAOM" || (
|
||||||
|
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 "============================================="
|
||||||
|
test -n "$SKIP_LIBAVIF" || (
|
||||||
|
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_enc"' \
|
||||||
|
--std=c++11 \
|
||||||
|
-I ./node_modules/libavif/include \
|
||||||
|
-o ./avif_enc.js \
|
||||||
|
-x c++ \
|
||||||
|
avif_enc.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 "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
||||||
11
codecs/avif_enc/example.js
Normal file
11
codecs/avif_enc/example.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const avifEnc = require("./avif_enc.js")(fs.readFileSync("./avif_enc.wasm"));
|
||||||
|
|
||||||
|
avifEnc.onRuntimeInitialized = () => {
|
||||||
|
const avif = avifEnc.encode(
|
||||||
|
new Uint8Array([255, 0, 0, 255, 0, 255, 0, 255, 0, 0, 255, 255]),
|
||||||
|
3,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
fs.writeFileSync("lol.avif", avif);
|
||||||
|
};
|
||||||
1147
codecs/avif_enc/package-lock.json
generated
Normal file
1147
codecs/avif_enc/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
codecs/avif_enc/package.json
Normal file
13
codecs/avif_enc/package.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "avif_enc",
|
||||||
|
"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