Skip to content

Commit

Permalink
Make webp compile
Browse files Browse the repository at this point in the history
  • Loading branch information
surma committed Aug 7, 2024
1 parent dd290ac commit a0f9fea
Show file tree
Hide file tree
Showing 28 changed files with 6,651 additions and 126 deletions.
53 changes: 10 additions & 43 deletions codecs/webp/Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
CODEC_URL = https://github.com/webmproject/libwebp/archive/d2e245ea9e959a5a79e1db0ed2085206947e98f2.tar.gz
CODEC_DIR = node_modules/libwebp
CODEC_BUILD_ROOT := $(CODEC_DIR)/build
CODEC_BASELINE_BUILD_DIR := $(CODEC_BUILD_ROOT)/baseline
CODEC_SIMD_BUILD_DIR := $(CODEC_BUILD_ROOT)/simd
ENVIRONMENT = worker

OUT_JS = enc/webp_enc.js enc/webp_enc_simd.js dec/webp_dec.js enc/webp_node_enc.js dec/webp_node_dec.js
# OUT_JS = enc/webp_enc.js enc/webp_enc_simd.js dec/webp_dec.js
OUT_JS = enc/webp_enc.js dec/webp_dec.js
OUT_WASM := $(OUT_JS:.js=.wasm)

.PHONY: all clean
Expand All @@ -15,54 +11,25 @@ all: $(OUT_JS)
# Define dependencies for all variations of build artifacts.
$(filter enc/%,$(OUT_JS)): enc/webp_enc.o
$(filter dec/%,$(OUT_JS)): dec/webp_dec.o
enc/webp_node_enc.js dec/webp_node_dec.js: ENVIRONMENT = node
enc/webp_node_enc.js dec/webp_node_dec.js: $(CODEC_BASELINE_BUILD_DIR)/libwebp.a
enc/webp_enc.js dec/webp_dec.js: $(CODEC_BASELINE_BUILD_DIR)/libwebp.a
enc/webp_enc_simd.js: $(CODEC_SIMD_BUILD_DIR)/libwebp.a
# enc/webp_enc.js dec/webp_dec.js: $(CODEC_BASELINE_BUILD_DIR)/libwebp.a
# enc/webp_enc_simd.js: $(CODEC_SIMD_BUILD_DIR)/libwebp.a

LIBWEBP_FLAGS = -I${WEBP}/include -L${WEBP}/lib -lwebp

$(OUT_JS):
$(LD) \
$(LIBWEBP_FLAGS) \
$(LDFLAGS) \
--bind \
-lembind \
-s ENVIRONMENT=$(ENVIRONMENT) \
-s EXPORT_ES6=1 \
-o $@ \
$+

%.o: %.cpp $(CODEC_DIR)/CMakeLists.txt
%.o: %.cpp
$(CXX) -c \
$(LIBWEBP_FLAGS) \
$(CXXFLAGS) \
-I $(CODEC_DIR) \
-o $@ \
$<

%/libwebp.a: %/Makefile
$(MAKE) -C $(@D)

# Enable SIMD on a SIMD build.
$(CODEC_SIMD_BUILD_DIR)/Makefile: CMAKE_FLAGS+=-DWEBP_ENABLE_SIMD=1

%/Makefile: $(CODEC_DIR)/CMakeLists.txt
emcmake cmake \
$(CMAKE_FLAGS) \
-DCMAKE_DISABLE_FIND_PACKAGE_Threads=1 \
-DWEBP_BUILD_ANIM_UTILS=0 \
-DWEBP_BUILD_CWEBP=0 \
-DWEBP_BUILD_DWEBP=0 \
-DWEBP_BUILD_GIF2WEBP=0 \
-DWEBP_BUILD_IMG2WEBP=0 \
-DWEBP_BUILD_VWEBP=0 \
-DWEBP_BUILD_WEBPINFO=0 \
-DWEBP_BUILD_WEBPMUX=0 \
-DWEBP_BUILD_EXTRAS=0 \
-B $(@D) \
$(<D)

$(CODEC_DIR)/CMakeLists.txt:
mkdir -p $(CODEC_DIR)
curl -sL $(CODEC_URL) | tar xz --strip 1 -C $(CODEC_DIR)

clean:
$(RM) $(OUT_JS) $(OUT_WASM)
$(MAKE) -C $(CODEC_BASELINE_BUILD_DIR) clean
$(MAKE) -C $(CODEC_SIMD_BUILD_DIR) clean
4 changes: 2 additions & 2 deletions codecs/webp/dec/webp_dec.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#include <string>
#include "emscripten/bind.h"
#include "emscripten/val.h"
#include "src/webp/decode.h"
#include "src/webp/demux.h"
#include "webp/decode.h"
#include "webp/demux.h"

using namespace emscripten;

Expand Down
16 changes: 0 additions & 16 deletions codecs/webp/dec/webp_dec.js

This file was deleted.

Binary file removed codecs/webp/dec/webp_dec.wasm
Binary file not shown.
16 changes: 0 additions & 16 deletions codecs/webp/dec/webp_node_dec.js

This file was deleted.

Binary file removed codecs/webp/dec/webp_node_dec.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion codecs/webp/enc/webp_enc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdexcept>
#include "src/webp/encode.h"
#include "webp/encode.h"

using namespace emscripten;

Expand Down
16 changes: 0 additions & 16 deletions codecs/webp/enc/webp_enc.js

This file was deleted.

Binary file removed codecs/webp/enc/webp_enc.wasm
Binary file not shown.
16 changes: 0 additions & 16 deletions codecs/webp/enc/webp_enc_simd.js

This file was deleted.

Binary file removed codecs/webp/enc/webp_enc_simd.wasm
Binary file not shown.
16 changes: 0 additions & 16 deletions codecs/webp/enc/webp_node_enc.js

This file was deleted.

Binary file removed codecs/webp/enc/webp_node_enc.wasm
Binary file not shown.
79 changes: 79 additions & 0 deletions codecs/webp/flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

107 changes: 107 additions & 0 deletions codecs/webp/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/24.05";
flake-utils.url = "github:numtide/flake-utils";
webp-src = {
url = "github:webmproject/libwebp/d2e245ea9e959a5a79e1db0ed2085206947e98f2";
flake = false;
};
};
outputs =
{
self,
nixpkgs,
flake-utils,
webp-src,
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
with pkgs;
rec {
packages = rec {
default = webp-squoosh;
webp-squoosh = stdenv.mkDerivation {
name = "mozjpeg-squoosh";
# Only copy files that are actually relevant to avoid unnecessary
# cache invalidations.
src = runCommand "src" { } ''
mkdir $out
cp -r ${./.}/enc $out/
cp -r ${./.}/dec $out/
cp ${./.}/Makefile $out/
'';
nativeBuildInputs = [
emscripten
webp
];
WEBP = webp;
dontConfigure = true;
buildPhase = ''
export HOME=$TMPDIR
emmake make -j$(nproc)
'';
installPhase = ''
mkdir -p $out
cp -r enc dec $out
'';
};
webp = stdenv.mkDerivation {
name = "webp";
src = webp-src;
nativeBuildInputs = [
# autoconf
# automake
# libtool
emscripten
# pkg-config
cmake
];
configurePhase = ''
# $HOME is required for Emscripten to work.
# See: https://nixos.org/manual/nixpkgs/stable/#emscripten
export HOME=$TMPDIR
mkdir -p $TMPDIR/build
emcmake cmake \
-DCMAKE_INSTALL_PREFIX=$out \
-DCMAKE_DISABLE_FIND_PACKAGE_Threads=1 \
-DWEBP_BUILD_ANIM_UTILS=0 \
-DWEBP_BUILD_CWEBP=0 \
-DWEBP_BUILD_DWEBP=0 \
-DWEBP_BUILD_GIF2WEBP=0 \
-DWEBP_BUILD_IMG2WEBP=0 \
-DWEBP_BUILD_VWEBP=0 \
-DWEBP_BUILD_WEBPINFO=0 \
-DWEBP_BUILD_WEBPMUX=0 \
-DWEBP_BUILD_EXTRAS=0 \
-B $TMPDIR/build \
.
'';
buildPhase = ''
export HOME=$TMPDIR
cd $TMPDIR/build
emmake make V=1 -j$(nproc) --trace
'';
installPhase = ''
cd $TMPDIR/build
make install
'';
dontFixup = true;
};
installScript = writeShellScriptBin "install.sh" ''
${pkgs.coreutils}/bin/rm -rf wasm_build
${pkgs.coreutils}/bin/mkdir -p wasm_build
${pkgs.rsync}/bin/rsync --chmod=u+w -r ${webp-squoosh}/* wasm_build/
'';
};
apps = {
install = {
type = "app";
program = "${packages.installScript}/bin/install.sh";
};
};
}
);
}
18 changes: 18 additions & 0 deletions codecs/webp/wasm_build/dec/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 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`.
20 changes: 20 additions & 0 deletions codecs/webp/wasm_build/dec/example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!doctype html>
<script src='webp_dec.js'></script>
<script>
async function loadFile(src) {
const resp = await fetch(src);
return await resp.arrayBuffer();
}

webp_dec().then(async module => {
console.log('Version:', module.version().toString(16));
const image = await loadFile('../../example.webp');
const imageData = module.decode(image);
const canvas = document.createElement('canvas');
canvas.width = imageData.width;
canvas.height = imageData.height;
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
ctx.putImageData(imageData, 0, 0);
});
</script>
29 changes: 29 additions & 0 deletions codecs/webp/wasm_build/dec/webp_dec.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <string>
#include "emscripten/bind.h"
#include "emscripten/val.h"
#include "webp/decode.h"
#include "webp/demux.h"

using namespace emscripten;

int version() {
return WebPGetDecoderVersion();
}

thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray");
thread_local const val ImageData = val::global("ImageData");

val decode(std::string buffer) {
int width, height;
std::unique_ptr<uint8_t[]> rgba(
WebPDecodeRGBA((const uint8_t*)buffer.c_str(), buffer.size(), &width, &height));
return rgba ? ImageData.new_(
Uint8ClampedArray.new_(typed_memory_view(width * height * 4, rgba.get())),
width, height)
: val::null();
}

EMSCRIPTEN_BINDINGS(my_module) {
function("decode", &decode);
function("version", &version);
}
7 changes: 7 additions & 0 deletions codecs/webp/wasm_build/dec/webp_dec.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface WebPModule extends EmscriptenWasm.Module {
decode(data: BufferSource): ImageData | null;
}

declare var moduleFactory: EmscriptenWasm.ModuleFactory<WebPModule>;

export default moduleFactory;
Loading

0 comments on commit a0f9fea

Please sign in to comment.