Skip to content

Commit

Permalink
Merge pull request #1000 from kleisauke/fix-emscripten-ci
Browse files Browse the repository at this point in the history
Fix Emscripten CI and demo
  • Loading branch information
farindk authored Oct 18, 2023
2 parents c7b7d50 + 00bcb84 commit 810a891
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 203 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/emscripten.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
jobs:
emscripten:
env:
EMSCRIPTEN_VERSION: 3.1.43
EMSCRIPTEN_VERSION: 3.1.47
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
Expand Down
23 changes: 12 additions & 11 deletions build-emscripten.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ if [ "$ENABLE_LIBDE265" = "1" ]; then
-L \
-o libde265-${LIBDE265_VERSION}.tar.gz \
https://github.com/strukturag/libde265/releases/download/v${LIBDE265_VERSION}/libde265-${LIBDE265_VERSION}.tar.gz
if [ ! -s "libde265-${LIBDE265_VERSION}/libde265/.libs/libde265.so" ]; then
if [ ! -s "libde265-${LIBDE265_VERSION}/libde265/.libs/libde265.a" ]; then
tar xf libde265-${LIBDE265_VERSION}.tar.gz
cd libde265-${LIBDE265_VERSION}
[ -x configure ] || ./autogen.sh
CXXFLAGS=-O3 emconfigure ./configure --disable-sse --disable-dec265 --disable-sherlock265
CXXFLAGS=-O3 emconfigure ./configure --enable-static --disable-shared --disable-sse --disable-dec265 --disable-sherlock265
emmake make -j${CORES}
cd ..
fi
Expand Down Expand Up @@ -72,7 +72,7 @@ if [ "$ENABLE_AOM" = "1" ]; then
-DENABLE_TOOLS=0 \
-DCONFIG_MULTITHREAD=0 \
-DCONFIG_RUNTIME_CPU_DETECT=0 \
-DBUILD_SHARED_LIBS=1 \
-DBUILD_SHARED_LIBS=0 \
-DCMAKE_BUILD_TYPE=Release

emmake make -j${CORES}
Expand All @@ -92,7 +92,7 @@ if [ "$STANDALONE" = "1" ]; then
EXTRA_COMPILER_FLAGS="-D__EMSCRIPTEN_STANDALONE_WASM__=1"
fi

CONFIGURE_ARGS="-DENABLE_MULTITHREADING_SUPPORT=OFF -DWITH_GDK_PIXBUF=OFF -DWITH_EXAMPLES=OFF -DBUILD_SHARED_LIBS=ON -DENABLE_PLUGIN_LOADING=OFF"
CONFIGURE_ARGS="-DENABLE_MULTITHREADING_SUPPORT=OFF -DWITH_GDK_PIXBUF=OFF -DWITH_EXAMPLES=OFF -DBUILD_SHARED_LIBS=OFF -DENABLE_PLUGIN_LOADING=OFF"
emcmake cmake ${SRCDIR} $CONFIGURE_ARGS \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_FLAGS="${EXTRA_COMPILER_FLAGS}" \
Expand All @@ -108,25 +108,26 @@ EXPORTED_FUNCTIONS=$($EMSDK/upstream/bin/llvm-nm $LIBHEIFA --format=just-symbols

echo "Running Emscripten..."

BUILD_FLAGS="-lembind -o libheif.js --pre-js ${SRCDIR}/pre.js --post-js ${SRCDIR}/post.js -sWASM=$USE_WASM"
BUILD_FLAGS="-lembind -o libheif.js --post-js ${SRCDIR}/post.js -sWASM=$USE_WASM"
RELEASE_BUILD_FLAGS="-O3"

if [ "$STANDALONE" = "1" ]; then
# Note: this intentionally overwrites the BUILD_FLAGS set above
echo "Building in standalone (non-web) build mode"
BUILD_FLAGS="-s STANDALONE_WASM=1 -s WASM=1 -o libheif.wasm --no-entry"
BUILD_FLAGS="-sSTANDALONE_WASM -sWASM -o libheif.wasm --no-entry"
fi

if [ "$DEBUG" = "1" ]; then
echo "Building in debug mode"
RELEASE_BUILD_FLAGS="--profile -g"
fi

emcc "$LIBHEIFA" \
-s EXPORTED_FUNCTIONS="$EXPORTED_FUNCTIONS,_free,_malloc,_memcpy" \
-s ALLOW_MEMORY_GROWTH=1 \
-s ERROR_ON_UNDEFINED_SYMBOLS=0 \
-s LLD_REPORT_UNDEFINED \
emcc -Wl,--whole-archive "$LIBHEIFA" -Wl,--no-whole-archive \
-sEXPORTED_FUNCTIONS="$EXPORTED_FUNCTIONS,_free,_malloc,_memcpy" \
-sMODULARIZE \
-sEXPORT_NAME="libheif" \
-sWASM_ASYNC_COMPILATION=0 \
-sALLOW_MEMORY_GROWTH \
--memory-init-file 0 \
-std=c++11 \
$LIBRARY_INCLUDE_FLAGS \
Expand Down
5 changes: 3 additions & 2 deletions examples/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ <h1>libheif decoder demo</h1>
}.bind(this));
this.drawer = new CanvasDrawer(canvas);
this.decoder = new libheif.HeifDecoder();

console.log("Using libheif", libheif.heif_get_version());
saveSupported = this.canvas.toBlob &&
((URL && URL.createObjectURL) || navigator.msSaveOrOpenBlob);
if (saveSupported) {
Expand Down Expand Up @@ -313,8 +315,7 @@ <h1>libheif decoder demo</h1>
return;
}

console.log("Using libheif", libheif.heif_get_version());
var demo = new HeifDemo(libheif);
var demo = new HeifDemo(libheif());

show("form");

Expand Down
7 changes: 6 additions & 1 deletion libheif/heif_emscripten.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,12 @@ EMSCRIPTEN_BINDINGS(libheif) {
emscripten::class_<heif_image>("heif_image");
emscripten::value_object<heif_error>("heif_error")
.field("code", &heif_error::code)
.field("subcode", &heif_error::subcode);
.field("subcode", &heif_error::subcode)
.field("message", emscripten::optional_override([](const struct heif_error& err) {
return std::string(err.message);
}), emscripten::optional_override([](struct heif_error& err, const std::string& value) {
err.message = value.c_str();
}));
}

#endif // LIBHEIF_BOX_EMSCRIPTEN_H
126 changes: 51 additions & 75 deletions post.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var HeifImage = function(handle) {

HeifImage.prototype.free = function() {
if (this.handle) {
libheif.heif_image_handle_release(this.handle);
Module.heif_image_handle_release(this.handle);
this.handle = null;
}
};
Expand All @@ -24,8 +24,8 @@ HeifImage.prototype._ensureImage = function() {
return;
}

var img = libheif.heif_js_decode_image(this.handle,
libheif.heif_colorspace_YCbCr, libheif.heif_chroma_420);
var img = Module.heif_js_decode_image(this.handle,
Module.heif_colorspace.heif_colorspace_YCbCr, Module.heif_chroma.heif_chroma_420);
if (!img || img.code) {
console.log("Decoding image failed", this.handle, img);
return;
Expand All @@ -36,17 +36,17 @@ HeifImage.prototype._ensureImage = function() {
this.img = img;

if (img.alpha !== undefined) {
this.alpha = new Uint8Array(StringToArrayBuffer(img.alpha));
delete img.alpha;
this.alpha = new Uint8Array(StringToArrayBuffer(img.alpha));
delete img.alpha;
}
};

HeifImage.prototype.get_width = function() {
return libheif.heif_image_handle_get_width(this.handle);
return Module.heif_image_handle_get_width(this.handle);
};

HeifImage.prototype.get_height = function() {
return libheif.heif_image_handle_get_height(this.handle);
return Module.heif_image_handle_get_height(this.handle);
};

HeifImage.prototype.is_primary = function() {
Expand All @@ -63,8 +63,8 @@ HeifImage.prototype.display = function(image_data, callback) {
// If image hasn't been loaded yet, decode the image

if (!this.img) {
var img = libheif.heif_js_decode_image2(this.handle,
libheif.heif_colorspace_RGB, libheif.heif_chroma_interleaved_RGBA);
var img = Module.heif_js_decode_image2(this.handle,
Module.heif_colorspace.heif_colorspace_RGB, Module.heif_chroma.heif_chroma_interleaved_RGBA);
if (!img || img.code) {
console.log("Decoding image failed", this.handle, img);

Expand All @@ -73,14 +73,13 @@ HeifImage.prototype.display = function(image_data, callback) {
}

for (let c of img.channels) {
if (c.id == libheif.heif_channel_interleaved) {
if (c.id == Module.heif_channel.heif_channel_interleaved) {

// copy image into output array

if (c.stride == c.width*4) {
if (c.stride == c.width * 4) {
image_data.data.set(c.data);
}
else {
} else {
for (let y = 0; y < c.height; y++) {
let slice = c.data.slice(y * c.stride, y * c.stride + c.width * 4);
let offset = y * c.width * 4;
Expand All @@ -90,7 +89,7 @@ HeifImage.prototype.display = function(image_data, callback) {
}
}

libheif.heif_image_release(img.image);
Module.heif_image_release(img.image);
}

callback(image_data);
Expand All @@ -103,32 +102,31 @@ var HeifDecoder = function() {

HeifDecoder.prototype.decode = function(buffer) {
if (this.decoder) {
libheif.heif_context_free(this.decoder);
Module.heif_context_free(this.decoder);
}
this.decoder = libheif.heif_context_alloc();
this.decoder = Module.heif_context_alloc();
if (!this.decoder) {
console.log("Could not create HEIF context");
return [];
}
var error = libheif.heif_context_read_from_memory(this.decoder, buffer);
if (error.code !== libheif.heif_error_Ok) {
console.log("Could not parse HEIF file", error);
var error = Module.heif_context_read_from_memory(this.decoder, buffer);
if (error.code !== Module.heif_error_code.heif_error_Ok) {
console.log("Could not parse HEIF file", error.message);
return [];
}

var ids = libheif.heif_js_context_get_list_of_top_level_image_IDs(this.decoder);
var ids = Module.heif_js_context_get_list_of_top_level_image_IDs(this.decoder);
if (!ids || ids.code) {
console.log("Error loading image ids", ids);
return [];
}
else if (!ids.length) {
} else if (!ids.length) {
console.log("No images found");
return [];
}

var result = [];
for (var i = 0; i < ids.length; i++) {
var handle = libheif.heif_js_context_get_image_handle(this.decoder, ids[i]);
var handle = Module.heif_js_context_get_image_handle(this.decoder, ids[i]);
if (!handle || handle.code) {
console.log("Could not get image data for id", ids[i], handle);
continue;
Expand All @@ -139,61 +137,39 @@ HeifDecoder.prototype.decode = function(buffer) {
return result;
};

var libheif = {
// Expose high-level API.
/** @expose */
HeifDecoder: HeifDecoder,

// Expose low-level API.
/** @expose */
fourcc: function(s) {
return s.charCodeAt(0) << 24 |
s.charCodeAt(1) << 16 |
s.charCodeAt(2) << 8 |
s.charCodeAt(3);
}
};

// don't pollute the global namespace
delete this['Module'];

// On IE this function is called with "undefined" as first parameter. Override
// with a version that supports this behaviour.
function createNamedFunction(name, body) {
if (!name) {
name = "function_" + (new Date());
}
name = makeLegalFunctionName(name);
/*jshint evil:true*/
return new Function(
"body",
"return function " + name + "() {\n" +
" \"use strict\";" +
" return body.apply(this, arguments);\n" +
"};\n"
)(body);
var fourcc = function(s) {
return s.charCodeAt(0) << 24 |
s.charCodeAt(1) << 16 |
s.charCodeAt(2) << 8 |
s.charCodeAt(3);
}

var root = this;

if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
/** @expose */
exports = module.exports = libheif;
Module.HeifImage = HeifImage;
Module.HeifDecoder = HeifDecoder;
Module.fourcc = fourcc;

// Expose enum values.
const enums = [
'heif_error_code',
'heif_suberror_code',
'heif_compression_format',
'heif_chroma',
'heif_colorspace',
'heif_channel'
];
for (const e of enums) {
for (const key in Module[e]) {
if (!Module[e].hasOwnProperty(key) || key === 'values') {
continue;
}
Module[key] = Module[e][key];
}
/** @expose */
exports.libheif = libheif;
} else {
/** @expose */
root.libheif = libheif;
}

if (typeof define === "function" && define.amd) {
/** @expose */
define([], function() {
return libheif;
});
// Expose internal C API.
for (const key in Module) {
if (key.indexOf('_heif_') !== 0 || Module[key.slice(1)] !== undefined) {
continue;
}
Module[key.slice(1)] = Module[key];
}

// NOTE: wrapped inside "(function() {" block from pre.js
}).call(this);
75 changes: 0 additions & 75 deletions pre.js

This file was deleted.

Loading

0 comments on commit 810a891

Please sign in to comment.