forked from external-repos/squoosh
Compare commits
38 Commits
dependabot
...
nix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13ff0d5934 | ||
|
|
2287e4517e | ||
|
|
16b75e7919 | ||
|
|
8a1c95b7dc | ||
|
|
d895e0a6b6 | ||
|
|
63441ef371 | ||
|
|
dfc9b36b6e | ||
|
|
aa7b284e65 | ||
|
|
24e63eafc6 | ||
|
|
00082becab | ||
|
|
fae5959392 | ||
|
|
53fc922870 | ||
|
|
4f93abb105 | ||
|
|
738d07d98a | ||
|
|
7e564e240a | ||
|
|
c1be464503 | ||
|
|
ee61b9fb18 | ||
|
|
6d061d8fa2 | ||
|
|
d278efb148 | ||
|
|
e4cec57fe3 | ||
|
|
a9c16df263 | ||
|
|
15df976a8c | ||
|
|
9bbfac62e8 | ||
|
|
13cbf8ddb1 | ||
|
|
b5bd766a4e | ||
|
|
a0f9fea679 | ||
|
|
dd290accc1 | ||
|
|
b19064702e | ||
|
|
3237a7e0ee | ||
|
|
c4cfc1d884 | ||
|
|
ba01d36c20 | ||
|
|
8c76d43a68 | ||
|
|
c308108279 | ||
|
|
2bd1eeceb8 | ||
|
|
95a16e3919 | ||
|
|
ec2a05ec33 | ||
|
|
11cd02c87b | ||
|
|
9ce5da7531 |
22
README.md
22
README.md
@@ -15,6 +15,8 @@ However, Squoosh utilizes Google Analytics to collect the following:
|
||||
|
||||
# Developing
|
||||
|
||||
## Web App
|
||||
|
||||
To develop for Squoosh:
|
||||
|
||||
1. Clone the repository
|
||||
@@ -31,8 +33,28 @@ To develop for Squoosh:
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Codecs
|
||||
|
||||
All build instructions for codecs are written using [Nix]. If you have Nix installed, you can rebuild the WebAssembly binaries by running:
|
||||
|
||||
```sh
|
||||
# Build the codec
|
||||
cd codec/<codec>
|
||||
nix run '.#updateRepoBinaries'
|
||||
```
|
||||
|
||||
If you do not have Nix installed, you can use the provided Docker image to create a shell with nix available:
|
||||
|
||||
```sh
|
||||
# Build the image (only needs to be done once).
|
||||
docker build -t squoosh-nix ./nix
|
||||
docker run --name squoosh-nix -ti -v $PWD:/app squoosh-nix /bin/sh
|
||||
# ... continue with the steps above
|
||||
```
|
||||
|
||||
# Contributing
|
||||
|
||||
Squoosh is an open-source project that appreciates all community involvement. To contribute to the project, follow the [contribute guide](/CONTRIBUTING.md).
|
||||
|
||||
[squoosh]: https://squoosh.app
|
||||
[nix]: https://nixos.org
|
||||
|
||||
1
codecs/.gitignore
vendored
Normal file
1
codecs/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!wasm_build
|
||||
@@ -1,61 +1,31 @@
|
||||
CODEC_URL := https://github.com/mozilla/mozjpeg/archive/v3.3.1.tar.gz
|
||||
CODEC_DIR := node_modules/mozjpeg
|
||||
CODEC_OUT_RELATIVE := .libs/libjpeg.a rdswitch.o
|
||||
CODEC_OUT := $(addprefix $(CODEC_DIR)/, $(CODEC_OUT_RELATIVE))
|
||||
ENVIRONMENT = worker
|
||||
|
||||
OUT_JS := enc/mozjpeg_enc.js enc/mozjpeg_node_enc.js dec/mozjpeg_node_dec.js
|
||||
OUT_JS := enc/mozjpeg_enc.js
|
||||
OUT_WASM := $(OUT_JS:.js=.wasm)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: $(OUT_JS)
|
||||
|
||||
# Define dependencies for all variations of build artifacts.
|
||||
$(filter enc/%,$(OUT_JS)): enc/mozjpeg_enc.cpp
|
||||
$(filter dec/%,$(OUT_JS)): dec/mozjpeg_dec.cpp
|
||||
|
||||
enc/mozjpeg_node_enc.js dec/mozjpeg_node_dec.js: ENVIRONMENT = node
|
||||
|
||||
%.js: $(CODEC_OUT)
|
||||
%.js:
|
||||
$(CXX) \
|
||||
-I $(CODEC_DIR) \
|
||||
${CXXFLAGS} \
|
||||
${LDFLAGS} \
|
||||
--bind \
|
||||
-O3 \
|
||||
-flto \
|
||||
-s FILESYSTEM=0 \
|
||||
-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
-s TEXTDECODER=2 \
|
||||
-s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 \
|
||||
-s ENVIRONMENT=$(ENVIRONMENT) \
|
||||
-s EXPORT_ES6=1 \
|
||||
-lembind \
|
||||
${CXXFLAGS} \
|
||||
${LDFLAGS} \
|
||||
-o $@ \
|
||||
-I ${MOZJPEG}/include \
|
||||
-L ${MOZJPEG}/lib \
|
||||
-ljpeg \
|
||||
${MOZJPEG}/lib/rdswitch.o \
|
||||
$+
|
||||
|
||||
# This one is a bit special: there is no rule for .libs/libjpeg.a
|
||||
# so we use libjpeg.la which implicitly builds that one instead.
|
||||
$(CODEC_DIR)/.libs/libjpeg.a: $(CODEC_DIR)/Makefile
|
||||
$(MAKE) -C $(CODEC_DIR) libjpeg.la
|
||||
|
||||
$(CODEC_DIR)/rdswitch.o: $(CODEC_DIR)/Makefile
|
||||
$(MAKE) -C $(CODEC_DIR) rdswitch.o
|
||||
|
||||
$(CODEC_DIR)/Makefile: $(CODEC_DIR)/configure
|
||||
cd $(CODEC_DIR) && ./configure \
|
||||
--disable-shared \
|
||||
--without-turbojpeg \
|
||||
--without-simd \
|
||||
--without-arith-enc \
|
||||
--without-arith-dec \
|
||||
--with-build-date=squoosh
|
||||
# ^ If not provided with a dummy value, MozJPEG includes a build date in the
|
||||
# binary as part of the version string, making binaries different each time.
|
||||
|
||||
$(CODEC_DIR)/configure: $(CODEC_DIR)/configure.ac
|
||||
cd $(CODEC_DIR) && autoreconf -iv
|
||||
|
||||
$(CODEC_DIR)/configure.ac: $(CODEC_DIR)
|
||||
|
||||
$(CODEC_DIR):
|
||||
mkdir -p $@
|
||||
curl -sL $(CODEC_URL) | tar xz --strip 1 -C $@
|
||||
|
||||
clean:
|
||||
$(RM) $(OUT_JS) $(OUT_WASM)
|
||||
$(MAKE) -C $(CODEC_DIR) clean
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
#include "config.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
extern "C" {
|
||||
#include "cdjpeg.h"
|
||||
}
|
||||
|
||||
using namespace emscripten;
|
||||
|
||||
thread_local const val Uint8ClampedArray = val::global("Uint8ClampedArray");
|
||||
thread_local const val ImageData = val::global("ImageData");
|
||||
|
||||
val decode(std::string image_in) {
|
||||
uint8_t* image_buffer = (uint8_t*)image_in.c_str();
|
||||
|
||||
jpeg_decompress_struct cinfo;
|
||||
jpeg_error_mgr jerr;
|
||||
// Initialize the JPEG decompression object with default error handling.
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jpeg_create_decompress(&cinfo);
|
||||
|
||||
jpeg_mem_src(&cinfo, image_buffer, image_in.length());
|
||||
// Read file header, set default decompression parameters
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
// Force RGBA decoding, even for grayscale images
|
||||
cinfo.out_color_space = JCS_EXT_RGBA;
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
// Prepare output buffer
|
||||
size_t output_size = cinfo.output_width * cinfo.output_height * 4;
|
||||
std::vector<uint8_t> output_buffer(output_size);
|
||||
auto stride = cinfo.output_width * 4;
|
||||
|
||||
// Process data
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
uint8_t* ptr = &output_buffer[stride * cinfo.output_scanline];
|
||||
jpeg_read_scanlines(&cinfo, &ptr, 1);
|
||||
}
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
|
||||
// Step 7: release JPEG compression object
|
||||
|
||||
auto data = Uint8ClampedArray.new_(typed_memory_view(output_size, &output_buffer[0]));
|
||||
auto js_result = ImageData.new_(data, cinfo.output_width, cinfo.output_height);
|
||||
|
||||
// This is an important step since it will release a good deal of memory.
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
// And we're done!
|
||||
return js_result;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(my_module) {
|
||||
function("decode", &decode);
|
||||
}
|
||||
16
codecs/mozjpeg/dec/mozjpeg_node_dec.js
generated
16
codecs/mozjpeg/dec/mozjpeg_node_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -5,7 +5,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "jconfig.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
16
codecs/mozjpeg/enc/mozjpeg_enc.js
generated
16
codecs/mozjpeg/enc/mozjpeg_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
16
codecs/mozjpeg/enc/mozjpeg_node_enc.js
generated
16
codecs/mozjpeg/enc/mozjpeg_node_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
79
codecs/mozjpeg/flake.lock
generated
Normal file
79
codecs/mozjpeg/flake.lock
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"mozjpeg-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1499684294,
|
||||
"narHash": "sha256-frpQdkk7bJE5qbV70fdL1FsC4eI0Fm8FWshqBQxCRtk=",
|
||||
"owner": "mozilla",
|
||||
"repo": "mozjpeg",
|
||||
"rev": "f154ccc091cbc22141cdfd531e5ad1fdc5bc53c7",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "mozilla",
|
||||
"ref": "v3.3.1",
|
||||
"repo": "mozjpeg",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1717179513,
|
||||
"narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "63dacb46bf939521bdc93981b4cbb7ecb58427a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"mozjpeg-src": "mozjpeg-src",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
92
codecs/mozjpeg/flake.nix
Normal file
92
codecs/mozjpeg/flake.nix
Normal file
@@ -0,0 +1,92 @@
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/24.05";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
mozjpeg-src = {
|
||||
url = "github:mozilla/mozjpeg/v3.3.1";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
mozjpeg-src,
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
inherit (pkgs) callPackage stdenv lib;
|
||||
|
||||
buildSquooshCppCodec = callPackage (import ../../nix/squoosh-cxx-builder) { };
|
||||
squooshHelpers = callPackage (import ../../nix/squoosh-helpers) { };
|
||||
inherit (squooshHelpers) forAllVariants mkRepoBinaryUpdater;
|
||||
|
||||
variants = {
|
||||
base = { };
|
||||
};
|
||||
|
||||
src = lib.sources.sourceByRegex ./. [
|
||||
"Makefile"
|
||||
"enc(/.+)?"
|
||||
];
|
||||
|
||||
builder = variantName: opts: {
|
||||
mozjpeg-squoosh = buildSquooshCppCodec {
|
||||
name = "mozjpeg-squoosh";
|
||||
inherit src;
|
||||
MOZJPEG = self.packages.${system}."mozjpeg-${variantName}";
|
||||
|
||||
dontConfigure = true;
|
||||
decoder = null;
|
||||
};
|
||||
|
||||
mozjpeg = stdenv.mkDerivation {
|
||||
name = "mozjpeg";
|
||||
src = mozjpeg-src;
|
||||
nativeBuildInputs = [
|
||||
pkgs.autoconf
|
||||
pkgs.automake
|
||||
pkgs.libtool
|
||||
pkgs.emscripten
|
||||
pkgs.pkg-config
|
||||
];
|
||||
configurePhase = ''
|
||||
# $HOME is required for Emscripten to work.
|
||||
# See: https://nixos.org/manual/nixpkgs/stable/#emscripten
|
||||
export HOME=$TMPDIR
|
||||
autoreconf -ifv
|
||||
emconfigure ./configure \
|
||||
--disable-shared \
|
||||
--without-turbojpeg \
|
||||
--without-simd \
|
||||
--without-arith-enc \
|
||||
--without-arith-dec \
|
||||
--with-build-date=squoosh \
|
||||
--prefix=$out
|
||||
'';
|
||||
buildPhase = ''
|
||||
export HOME=$TMPDIR
|
||||
emmake make V=1 -j$(nproc) --trace
|
||||
'';
|
||||
installPhase = ''
|
||||
make install
|
||||
cp *.h $out/include
|
||||
cp rdswitch.o $out/lib
|
||||
'';
|
||||
dontFixup = true;
|
||||
};
|
||||
};
|
||||
|
||||
packageVariants = forAllVariants { inherit builder variants; };
|
||||
in
|
||||
|
||||
mkRepoBinaryUpdater {
|
||||
packages = packageVariants // {
|
||||
default = packageVariants."mozjpeg-squoosh-base";
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
4
codecs/mozjpeg/package-lock.json
generated
4
codecs/mozjpeg/package-lock.json
generated
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"name": "mozjpeg_enc",
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"scripts": {
|
||||
"build": "../build-cpp.sh"
|
||||
}
|
||||
}
|
||||
239
codecs/mozjpeg/wasm_build/enc/mozjpeg_enc.cpp
Normal file
239
codecs/mozjpeg/wasm_build/enc/mozjpeg_enc.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
#include <inttypes.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jconfig.h"
|
||||
#include "jpeglib.h"
|
||||
|
||||
extern "C" {
|
||||
#include "cdjpeg.h"
|
||||
}
|
||||
|
||||
using namespace emscripten;
|
||||
|
||||
// MozJPEG doesn’t expose a numeric version, so I have to do some fun C macro
|
||||
// hackery to turn it into a string. More details here:
|
||||
// https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
struct MozJpegOptions {
|
||||
int quality;
|
||||
bool baseline;
|
||||
bool arithmetic;
|
||||
bool progressive;
|
||||
bool optimize_coding;
|
||||
int smoothing;
|
||||
int color_space;
|
||||
int quant_table;
|
||||
bool trellis_multipass;
|
||||
bool trellis_opt_zero;
|
||||
bool trellis_opt_table;
|
||||
int trellis_loops;
|
||||
bool auto_subsample;
|
||||
int chroma_subsample;
|
||||
bool separate_chroma_quality;
|
||||
int chroma_quality;
|
||||
};
|
||||
|
||||
int version() {
|
||||
char buffer[] = xstr(MOZJPEG_VERSION);
|
||||
int version = 0;
|
||||
int last_index = 0;
|
||||
for (int i = 0; i < strlen(buffer); i++) {
|
||||
if (buffer[i] == '.') {
|
||||
buffer[i] = '\0';
|
||||
version = version << 8 | atoi(&buffer[last_index]);
|
||||
buffer[i] = '.';
|
||||
last_index = i + 1;
|
||||
}
|
||||
}
|
||||
version = version << 8 | atoi(&buffer[last_index]);
|
||||
return version;
|
||||
}
|
||||
|
||||
thread_local const val Uint8Array = val::global("Uint8Array");
|
||||
|
||||
val encode(std::string image_in, int image_width, int image_height, MozJpegOptions opts) {
|
||||
uint8_t* image_buffer = (uint8_t*)image_in.c_str();
|
||||
|
||||
// The code below is basically the `write_JPEG_file` function from
|
||||
// https://github.com/mozilla/mozjpeg/blob/master/example.c
|
||||
// I just write to memory instead of a file.
|
||||
|
||||
/* Step 1: allocate and initialize JPEG compression object */
|
||||
|
||||
/* This struct contains the JPEG compression parameters and pointers to
|
||||
* working space (which is allocated as needed by the JPEG library).
|
||||
* It is possible to have several such structures, representing multiple
|
||||
* compression/decompression processes, in existence at once. We refer
|
||||
* to any one struct (and its associated working data) as a "JPEG object".
|
||||
*/
|
||||
jpeg_compress_struct cinfo;
|
||||
/* This struct represents a JPEG error handler. It is declared separately
|
||||
* because applications often want to supply a specialized error handler
|
||||
* (see the second half of this file for an example). But here we just
|
||||
* take the easy way out and use the standard error handler, which will
|
||||
* print a message on stderr and call exit() if compression fails.
|
||||
* Note that this struct must live as long as the main JPEG parameter
|
||||
* struct, to avoid dangling-pointer problems.
|
||||
*/
|
||||
jpeg_error_mgr jerr;
|
||||
/* We have to set up the error handler first, in case the initialization
|
||||
* step fails. (Unlikely, but it could happen if you are out of memory.)
|
||||
* This routine fills in the contents of struct jerr, and returns jerr's
|
||||
* address which we place into the link field in cinfo.
|
||||
*/
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
/* Now we can initialize the JPEG compression object. */
|
||||
jpeg_create_compress(&cinfo);
|
||||
|
||||
/* Step 2: specify data destination (eg, a file) */
|
||||
/* Note: steps 2 and 3 can be done in either order. */
|
||||
|
||||
/* Here we use the library-supplied code to send compressed data to a
|
||||
* stdio stream. You can also write your own code to do something else.
|
||||
* VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
|
||||
* requires it in order to write binary files.
|
||||
*/
|
||||
// if ((outfile = fopen(filename, "wb")) == NULL) {
|
||||
// fprintf(stderr, "can't open %s\n", filename);
|
||||
// exit(1);
|
||||
// }
|
||||
uint8_t* output = nullptr;
|
||||
unsigned long size = 0;
|
||||
jpeg_mem_dest(&cinfo, &output, &size);
|
||||
|
||||
/* Step 3: set parameters for compression */
|
||||
|
||||
/* First we supply a description of the input image.
|
||||
* Four fields of the cinfo struct must be filled in:
|
||||
*/
|
||||
cinfo.image_width = image_width; /* image width and height, in pixels */
|
||||
cinfo.image_height = image_height;
|
||||
cinfo.input_components = 4; /* # of color components per pixel */
|
||||
cinfo.in_color_space = JCS_EXT_RGBA; /* colorspace of input image */
|
||||
/* Now use the library's routine to set default compression parameters.
|
||||
* (You must set at least cinfo.in_color_space before calling this,
|
||||
* since the defaults depend on the source color space.)
|
||||
*/
|
||||
jpeg_set_defaults(&cinfo);
|
||||
|
||||
jpeg_set_colorspace(&cinfo, (J_COLOR_SPACE)opts.color_space);
|
||||
|
||||
if (opts.quant_table != -1) {
|
||||
jpeg_c_set_int_param(&cinfo, JINT_BASE_QUANT_TBL_IDX, opts.quant_table);
|
||||
}
|
||||
|
||||
cinfo.optimize_coding = opts.optimize_coding;
|
||||
|
||||
if (opts.arithmetic) {
|
||||
cinfo.arith_code = TRUE;
|
||||
cinfo.optimize_coding = FALSE;
|
||||
}
|
||||
|
||||
cinfo.smoothing_factor = opts.smoothing;
|
||||
|
||||
jpeg_c_set_bool_param(&cinfo, JBOOLEAN_USE_SCANS_IN_TRELLIS, opts.trellis_multipass);
|
||||
jpeg_c_set_bool_param(&cinfo, JBOOLEAN_TRELLIS_EOB_OPT, opts.trellis_opt_zero);
|
||||
jpeg_c_set_bool_param(&cinfo, JBOOLEAN_TRELLIS_Q_OPT, opts.trellis_opt_table);
|
||||
jpeg_c_set_int_param(&cinfo, JINT_TRELLIS_NUM_LOOPS, opts.trellis_loops);
|
||||
jpeg_c_set_int_param(&cinfo, JINT_DC_SCAN_OPT_MODE, 0);
|
||||
|
||||
// A little hacky to build a string for this, but it means we can use
|
||||
// set_quality_ratings which does some useful heuristic stuff.
|
||||
std::string quality_str = std::to_string(opts.quality);
|
||||
|
||||
if (opts.separate_chroma_quality && opts.color_space == JCS_YCbCr) {
|
||||
quality_str += "," + std::to_string(opts.chroma_quality);
|
||||
}
|
||||
|
||||
char const* pqual = quality_str.c_str();
|
||||
|
||||
set_quality_ratings(&cinfo, (char*)pqual, opts.baseline);
|
||||
|
||||
if (!opts.auto_subsample && opts.color_space == JCS_YCbCr) {
|
||||
cinfo.comp_info[0].h_samp_factor = opts.chroma_subsample;
|
||||
cinfo.comp_info[0].v_samp_factor = opts.chroma_subsample;
|
||||
|
||||
if (opts.chroma_subsample > 2) {
|
||||
// Otherwise encoding fails.
|
||||
jpeg_c_set_int_param(&cinfo, JINT_DC_SCAN_OPT_MODE, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!opts.baseline && opts.progressive) {
|
||||
jpeg_simple_progression(&cinfo);
|
||||
} else {
|
||||
cinfo.num_scans = 0;
|
||||
cinfo.scan_info = NULL;
|
||||
}
|
||||
/* Step 4: Start compressor */
|
||||
|
||||
/* TRUE ensures that we will write a complete interchange-JPEG file.
|
||||
* Pass TRUE unless you are very sure of what you're doing.
|
||||
*/
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
/* Step 5: while (scan lines remain to be written) */
|
||||
/* jpeg_write_scanlines(...); */
|
||||
|
||||
/* Here we use the library's state variable cinfo.next_scanline as the
|
||||
* loop counter, so that we don't have to keep track ourselves.
|
||||
* To keep things simple, we pass one scanline per call; you can pass
|
||||
* more if you wish, though.
|
||||
*/
|
||||
int row_stride = image_width * 4; /* JSAMPLEs per row in image_buffer */
|
||||
|
||||
while (cinfo.next_scanline < cinfo.image_height) {
|
||||
/* jpeg_write_scanlines expects an array of pointers to scanlines.
|
||||
* Here the array is only one element long, but you could pass
|
||||
* more than one scanline at a time if that's more convenient.
|
||||
*/
|
||||
|
||||
JSAMPROW row_pointer =
|
||||
&image_buffer[cinfo.next_scanline * row_stride]; /* pointer to JSAMPLE row[s] */
|
||||
(void)jpeg_write_scanlines(&cinfo, &row_pointer, 1);
|
||||
}
|
||||
|
||||
/* Step 6: Finish compression */
|
||||
|
||||
jpeg_finish_compress(&cinfo);
|
||||
|
||||
/* Step 7: release JPEG compression object */
|
||||
|
||||
auto js_result = Uint8Array.new_(typed_memory_view(size, output));
|
||||
|
||||
/* This is an important step since it will release a good deal of memory. */
|
||||
jpeg_destroy_compress(&cinfo);
|
||||
free(output);
|
||||
|
||||
/* And we're done! */
|
||||
return js_result;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(my_module) {
|
||||
value_object<MozJpegOptions>("MozJpegOptions")
|
||||
.field("quality", &MozJpegOptions::quality)
|
||||
.field("baseline", &MozJpegOptions::baseline)
|
||||
.field("arithmetic", &MozJpegOptions::arithmetic)
|
||||
.field("progressive", &MozJpegOptions::progressive)
|
||||
.field("optimize_coding", &MozJpegOptions::optimize_coding)
|
||||
.field("smoothing", &MozJpegOptions::smoothing)
|
||||
.field("color_space", &MozJpegOptions::color_space)
|
||||
.field("quant_table", &MozJpegOptions::quant_table)
|
||||
.field("trellis_multipass", &MozJpegOptions::trellis_multipass)
|
||||
.field("trellis_opt_zero", &MozJpegOptions::trellis_opt_zero)
|
||||
.field("trellis_opt_table", &MozJpegOptions::trellis_opt_table)
|
||||
.field("trellis_loops", &MozJpegOptions::trellis_loops)
|
||||
.field("chroma_subsample", &MozJpegOptions::chroma_subsample)
|
||||
.field("auto_subsample", &MozJpegOptions::auto_subsample)
|
||||
.field("separate_chroma_quality", &MozJpegOptions::separate_chroma_quality)
|
||||
.field("chroma_quality", &MozJpegOptions::chroma_quality);
|
||||
|
||||
function("version", &version);
|
||||
function("encode", &encode);
|
||||
}
|
||||
37
codecs/mozjpeg/wasm_build/enc/mozjpeg_enc.d.ts
vendored
Normal file
37
codecs/mozjpeg/wasm_build/enc/mozjpeg_enc.d.ts
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
export const enum MozJpegColorSpace {
|
||||
GRAYSCALE = 1,
|
||||
RGB,
|
||||
YCbCr,
|
||||
}
|
||||
|
||||
export interface EncodeOptions {
|
||||
quality: number;
|
||||
baseline: boolean;
|
||||
arithmetic: boolean;
|
||||
progressive: boolean;
|
||||
optimize_coding: boolean;
|
||||
smoothing: number;
|
||||
color_space: MozJpegColorSpace;
|
||||
quant_table: number;
|
||||
trellis_multipass: boolean;
|
||||
trellis_opt_zero: boolean;
|
||||
trellis_opt_table: boolean;
|
||||
trellis_loops: number;
|
||||
auto_subsample: boolean;
|
||||
chroma_subsample: number;
|
||||
separate_chroma_quality: boolean;
|
||||
chroma_quality: number;
|
||||
}
|
||||
|
||||
export interface MozJPEGModule extends EmscriptenWasm.Module {
|
||||
encode(
|
||||
data: BufferSource,
|
||||
width: number,
|
||||
height: number,
|
||||
options: EncodeOptions,
|
||||
): Uint8Array;
|
||||
}
|
||||
|
||||
declare var moduleFactory: EmscriptenWasm.ModuleFactory<MozJPEGModule>;
|
||||
|
||||
export default moduleFactory;
|
||||
16
codecs/mozjpeg/wasm_build/enc/mozjpeg_enc.js
generated
Normal file
16
codecs/mozjpeg/wasm_build/enc/mozjpeg_enc.js
generated
Normal file
File diff suppressed because one or more lines are too long
BIN
codecs/mozjpeg/wasm_build/enc/mozjpeg_enc.wasm
Executable file
BIN
codecs/mozjpeg/wasm_build/enc/mozjpeg_enc.wasm
Executable file
Binary file not shown.
115
codecs/resize/flake.lock
generated
Normal file
115
codecs/resize/flake.lock
generated
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"nodes": {
|
||||
"fenix": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1723616992,
|
||||
"narHash": "sha256-jDHYfEECzFwZm4huz7AbPjlH3jJ4/2ns9PddtFA5XMY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "7bad6c7ff73b784a9c7de9147626c8d5d5072809",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "7bad6c7ff73b784a9c7de9147626c8d5d5072809",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1725432240,
|
||||
"narHash": "sha256-+yj+xgsfZaErbfYM3T+QvEE2hU7UuE+Jf0fJCJ8uPS0=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ad416d066ca1222956472ab7d0555a6946746a80",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1717179513,
|
||||
"narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "63dacb46bf939521bdc93981b4cbb7ecb58427a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"fenix": "fenix",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
}
|
||||
},
|
||||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1725548942,
|
||||
"narHash": "sha256-ZnF5MaOAeiiKIATYN4rrqNsnhSQOQ+Hvfg0mHLvN04Y=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "124c7482167ff6eea4f7663c0be87ea568ccd8c6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rust-lang",
|
||||
"ref": "nightly",
|
||||
"repo": "rust-analyzer",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
57
codecs/resize/flake.nix
Normal file
57
codecs/resize/flake.nix
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/24.05";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
fenix.url = "github:nix-community/fenix/7bad6c7ff73b784a9c7de9147626c8d5d5072809";
|
||||
};
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
fenix,
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
inherit (pkgs) callPackage lib;
|
||||
|
||||
buildSquooshRustCodec = callPackage (import ../../nix/squoosh-rust-builder) {
|
||||
fenix = fenix.packages.${system};
|
||||
};
|
||||
squooshHelpers = callPackage (import ../../nix/squoosh-helpers) { };
|
||||
inherit (squooshHelpers) mkRepoBinaryUpdater forAllVariants;
|
||||
|
||||
variants = {
|
||||
base = { };
|
||||
};
|
||||
|
||||
src = lib.sources.sourceByRegex ./. [
|
||||
"Cargo.*"
|
||||
"build\.rs"
|
||||
"src(/.+)?"
|
||||
];
|
||||
|
||||
builder = variantName: opts: {
|
||||
resize-squoosh = buildSquooshRustCodec {
|
||||
name = "resize-squoosh";
|
||||
inherit src;
|
||||
cargoLock = {
|
||||
lockFile = "${src}/Cargo.lock";
|
||||
};
|
||||
wasmBindgen = {
|
||||
sha256 = "sha256-HTElSB76gqCpDu8S0ZJlfd/S4ftMrbwxFgJM9OXBRz8=";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
packageVariants = forAllVariants { inherit builder variants; };
|
||||
in
|
||||
mkRepoBinaryUpdater {
|
||||
packages = packageVariants // {
|
||||
default = packageVariants."resize-squoosh-base";
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
4
codecs/resize/package-lock.json
generated
4
codecs/resize/package-lock.json
generated
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"name": "resize",
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "resize",
|
||||
"scripts": {
|
||||
"build": "../build-rust.sh"
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"name": "squoosh-resize",
|
||||
"collaborators": [
|
||||
"Surma <surma@surma.link>"
|
||||
],
|
||||
"version": "0.1.0",
|
||||
"files": [
|
||||
"squoosh_resize_bg.wasm",
|
||||
"squoosh_resize.js",
|
||||
"squoosh_resize.d.ts"
|
||||
],
|
||||
"module": "squoosh_resize.js",
|
||||
"types": "squoosh_resize.d.ts",
|
||||
"sideEffects": false
|
||||
}
|
||||
Binary file not shown.
BIN
codecs/resize/wasm_build/squoosh_resize_bg.wasm
Normal file
BIN
codecs/resize/wasm_build/squoosh_resize_bg.wasm
Normal file
Binary file not shown.
115
codecs/rotate/flake.lock
generated
Normal file
115
codecs/rotate/flake.lock
generated
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"nodes": {
|
||||
"fenix": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs",
|
||||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1723616992,
|
||||
"narHash": "sha256-jDHYfEECzFwZm4huz7AbPjlH3jJ4/2ns9PddtFA5XMY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "7bad6c7ff73b784a9c7de9147626c8d5d5072809",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "7bad6c7ff73b784a9c7de9147626c8d5d5072809",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1723362943,
|
||||
"narHash": "sha256-dFZRVSgmJkyM0bkPpaYRtG/kRMRTorUIDj8BxoOt1T4=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a58bc8ad779655e790115244571758e8de055e3d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1717179513,
|
||||
"narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "63dacb46bf939521bdc93981b4cbb7ecb58427a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"fenix": "fenix",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
}
|
||||
},
|
||||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1723561310,
|
||||
"narHash": "sha256-a3KMMsIDvdo+ClLabh5wfJoa17YTSvy2wDLb8yZCXvc=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "78c2bdce860dbd996a8083224d01a96660dd6a15",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rust-lang",
|
||||
"ref": "nightly",
|
||||
"repo": "rust-analyzer",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
54
codecs/rotate/flake.nix
Normal file
54
codecs/rotate/flake.nix
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/24.05";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
fenix.url = "github:nix-community/fenix/7bad6c7ff73b784a9c7de9147626c8d5d5072809";
|
||||
};
|
||||
outputs =
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
fenix,
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
inherit (pkgs) callPackage lib;
|
||||
|
||||
buildSquooshRustCodec = callPackage (import ../../nix/squoosh-rust-builder) {
|
||||
fenix = fenix.packages.${system};
|
||||
};
|
||||
squooshHelpers = callPackage (import ../../nix/squoosh-helpers) { };
|
||||
inherit (squooshHelpers) mkRepoBinaryUpdater forAllVariants;
|
||||
|
||||
variants = {
|
||||
base = { };
|
||||
};
|
||||
|
||||
src = lib.sources.sourceByRegex ./. [
|
||||
"Cargo\.*"
|
||||
".*\.rs"
|
||||
];
|
||||
|
||||
builder = variantName: opts: {
|
||||
rotate-squoosh = buildSquooshRustCodec {
|
||||
name = "rotate-squoosh";
|
||||
inherit src;
|
||||
cargoLock = {
|
||||
lockFile = "${src}/Cargo.lock";
|
||||
};
|
||||
wasmBindgen = null;
|
||||
};
|
||||
};
|
||||
|
||||
packageVariants = forAllVariants { inherit builder variants; };
|
||||
in
|
||||
mkRepoBinaryUpdater {
|
||||
packages = packageVariants // {
|
||||
default = packageVariants."rotate-squoosh-base";
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
Binary file not shown.
BIN
codecs/rotate/wasm_build/optimized.wasm
Normal file
BIN
codecs/rotate/wasm_build/optimized.wasm
Normal file
Binary file not shown.
@@ -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
|
||||
@@ -15,54 +11,41 @@ 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) \
|
||||
-O3 \
|
||||
-flto \
|
||||
-std=c++17 \
|
||||
-s FILESYSTEM=0 \
|
||||
-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
-s TEXTDECODER=2 \
|
||||
-s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 \
|
||||
$(LIBWEBP_FLAGS) \
|
||||
$(LDFLAGS) \
|
||||
--bind \
|
||||
-lembind \
|
||||
-s ENVIRONMENT=$(ENVIRONMENT) \
|
||||
-s EXPORT_ES6=1 \
|
||||
-o $@ \
|
||||
$+
|
||||
|
||||
%.o: %.cpp $(CODEC_DIR)/CMakeLists.txt
|
||||
%.o: %.cpp
|
||||
$(CXX) -c \
|
||||
-O3 \
|
||||
-flto \
|
||||
-std=c++17 \
|
||||
-s FILESYSTEM=0 \
|
||||
-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
-s TEXTDECODER=2 \
|
||||
-s NODEJS_CATCH_EXIT=0 -s NODEJS_CATCH_REJECTION=0 \
|
||||
$(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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
16
codecs/webp/dec/webp_dec.js
generated
16
codecs/webp/dec/webp_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
16
codecs/webp/dec/webp_node_dec.js
generated
16
codecs/webp/dec/webp_node_dec.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -3,7 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
#include "src/webp/encode.h"
|
||||
#include "webp/encode.h"
|
||||
|
||||
using namespace emscripten;
|
||||
|
||||
|
||||
16
codecs/webp/enc/webp_enc.js
generated
16
codecs/webp/enc/webp_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
16
codecs/webp/enc/webp_enc_simd.js
generated
16
codecs/webp/enc/webp_enc_simd.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
16
codecs/webp/enc/webp_node_enc.js
generated
16
codecs/webp/enc/webp_node_enc.js
generated
File diff suppressed because one or more lines are too long
Binary file not shown.
79
codecs/webp/flake.lock
generated
Normal file
79
codecs/webp/flake.lock
generated
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1717179513,
|
||||
"narHash": "sha256-vboIEwIQojofItm2xGCdZCzW96U85l9nDW3ifMuAIdM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "63dacb46bf939521bdc93981b4cbb7ecb58427a0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "24.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"webp-src": "webp-src"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"webp-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1606186400,
|
||||
"narHash": "sha256-Emwd2wFbBONurMXSp8iwtwnSHgw4vcqBpuG0gyhZjFA=",
|
||||
"owner": "webmproject",
|
||||
"repo": "libwebp",
|
||||
"rev": "d2e245ea9e959a5a79e1db0ed2085206947e98f2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "webmproject",
|
||||
"repo": "libwebp",
|
||||
"rev": "d2e245ea9e959a5a79e1db0ed2085206947e98f2",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
130
codecs/webp/flake.nix
Normal file
130
codecs/webp/flake.nix
Normal file
@@ -0,0 +1,130 @@
|
||||
{
|
||||
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};
|
||||
inherit (pkgs) lib stdenv callPackage;
|
||||
buildSquooshCppCodec = callPackage (import ../../nix/squoosh-cxx-builder) { };
|
||||
squooshHelpers = callPackage (import ../../nix/squoosh-helpers) { };
|
||||
inherit (squooshHelpers) forAllVariants mkRepoBinaryUpdater;
|
||||
|
||||
variants = {
|
||||
base = {
|
||||
simd = false;
|
||||
};
|
||||
simd = {
|
||||
simd = true;
|
||||
};
|
||||
};
|
||||
|
||||
src = lib.sources.sourceByRegex ./. [
|
||||
"Makefile"
|
||||
"enc(/.+)?"
|
||||
"dec(/.+)?"
|
||||
];
|
||||
|
||||
builder =
|
||||
variantName:
|
||||
{ simd }:
|
||||
{
|
||||
"webp-squoosh" = buildSquooshCppCodec {
|
||||
name = "webp-squoosh-${variantName}";
|
||||
inherit src;
|
||||
nativeBuildInputs = [
|
||||
pkgs.emscripten
|
||||
self.packages.${system}."webp-${variantName}"
|
||||
];
|
||||
WEBP = self.packages.${system}."webp-${variantName}";
|
||||
dontConfigure = true;
|
||||
buildPhase = ''
|
||||
export HOME=$TMPDIR
|
||||
emmake make -j$(nproc)
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp -r enc dec $out
|
||||
'';
|
||||
};
|
||||
"webp" = stdenv.mkDerivation {
|
||||
name = "webp-${variantName}";
|
||||
src = webp-src;
|
||||
nativeBuildInputs = [
|
||||
pkgs.emscripten
|
||||
pkgs.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 \
|
||||
${if simd then "-DWEBP_ENABLE_SIMD=1" else ""} \
|
||||
-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;
|
||||
};
|
||||
};
|
||||
|
||||
packageVariants = forAllVariants { inherit builder variants; };
|
||||
|
||||
defaultPackage =
|
||||
let
|
||||
copyAllCodecs = lib.concatLines (
|
||||
lib.mapAttrsToList (
|
||||
name: _: "cp -r ${packageVariants."webp-squoosh-${name}"} $out/${name}"
|
||||
) variants
|
||||
);
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
name = "all-variants";
|
||||
phases = [ "buildPhase" ];
|
||||
buildPhase = ''
|
||||
mkdir -p $out;
|
||||
${copyAllCodecs}
|
||||
'';
|
||||
};
|
||||
in
|
||||
|
||||
mkRepoBinaryUpdater {
|
||||
packages = packageVariants // {
|
||||
default = defaultPackage;
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
18
codecs/webp/wasm_build/base/dec/README.md
Normal file
18
codecs/webp/wasm_build/base/dec/README.md
Normal file
@@ -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
codecs/webp/wasm_build/base/dec/example.html
Normal file
20
codecs/webp/wasm_build/base/dec/example.html
Normal file
@@ -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
codecs/webp/wasm_build/base/dec/webp_dec.cpp
Normal file
29
codecs/webp/wasm_build/base/dec/webp_dec.cpp
Normal file
@@ -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
codecs/webp/wasm_build/base/dec/webp_dec.d.ts
vendored
Normal file
7
codecs/webp/wasm_build/base/dec/webp_dec.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface WebPModule extends EmscriptenWasm.Module {
|
||||
decode(data: BufferSource): ImageData | null;
|
||||
}
|
||||
|
||||
declare var moduleFactory: EmscriptenWasm.ModuleFactory<WebPModule>;
|
||||
|
||||
export default moduleFactory;
|
||||
16
codecs/webp/wasm_build/base/dec/webp_dec.js
generated
Normal file
16
codecs/webp/wasm_build/base/dec/webp_dec.js
generated
Normal file
File diff suppressed because one or more lines are too long
BIN
codecs/webp/wasm_build/base/dec/webp_dec.wasm
Executable file
BIN
codecs/webp/wasm_build/base/dec/webp_dec.wasm
Executable file
Binary file not shown.
22
codecs/webp/wasm_build/base/enc/README.md
Normal file
22
codecs/webp/wasm_build/base/enc/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# WebP encoder
|
||||
|
||||
- Source: <https://github.com/webmproject/libwebp>
|
||||
- Version: v1.0.2
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Docker
|
||||
|
||||
## Example
|
||||
|
||||
See `example.html`
|
||||
|
||||
## API
|
||||
|
||||
### `int version()`
|
||||
|
||||
Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c
|
||||
|
||||
### `UInt8Array encode(uint8_t* image_buffer, int image_width, int image_height, WebPConfig config)`
|
||||
|
||||
Encodes the given image with given dimension to WebP.
|
||||
58
codecs/webp/wasm_build/base/enc/example.html
Normal file
58
codecs/webp/wasm_build/base/enc/example.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<!doctype html>
|
||||
<script src='webp_enc.js'></script>
|
||||
<script>
|
||||
async function loadImage(src) {
|
||||
// Load image
|
||||
const img = document.createElement('img');
|
||||
img.src = src;
|
||||
await new Promise(resolve => img.onload = resolve);
|
||||
// Make canvas same size as image
|
||||
const canvas = document.createElement('canvas');
|
||||
[canvas.width, canvas.height] = [img.width, img.height];
|
||||
// Draw image onto canvas
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0);
|
||||
return ctx.getImageData(0, 0, img.width, img.height);
|
||||
}
|
||||
|
||||
webp_enc().then(async module => {
|
||||
console.log('Version:', module.version().toString(16));
|
||||
const image = await loadImage('../../example.png');
|
||||
const result = module.encode(image.data, image.width, image.height, {
|
||||
quality: 75,
|
||||
target_size: 0,
|
||||
target_PSNR: 0,
|
||||
method: 4,
|
||||
sns_strength: 50,
|
||||
filter_strength: 60,
|
||||
filter_sharpness: 0,
|
||||
filter_type: 1,
|
||||
partitions: 0,
|
||||
segments: 4,
|
||||
pass: 1,
|
||||
show_compressed: 0,
|
||||
preprocessing: 0,
|
||||
autofilter: 0,
|
||||
partition_limit: 0,
|
||||
alpha_compression: 1,
|
||||
alpha_filtering: 1,
|
||||
alpha_quality: 100,
|
||||
lossless: 0,
|
||||
exact: 0,
|
||||
image_hint: 0,
|
||||
emulate_jpeg_size: 0,
|
||||
thread_level: 0,
|
||||
low_memory: 0,
|
||||
near_lossless: 100,
|
||||
use_delta_palette: 0,
|
||||
use_sharp_yuv: 0,
|
||||
});
|
||||
console.log('size', result.length);
|
||||
const blob = new Blob([result], {type: 'image/webp'});
|
||||
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
const img = document.createElement('img');
|
||||
img.src = blobURL;
|
||||
document.body.appendChild(img);
|
||||
});
|
||||
</script>
|
||||
85
codecs/webp/wasm_build/base/enc/webp_enc.cpp
Normal file
85
codecs/webp/wasm_build/base/enc/webp_enc.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
#include "webp/encode.h"
|
||||
|
||||
using namespace emscripten;
|
||||
|
||||
int version() {
|
||||
return WebPGetEncoderVersion();
|
||||
}
|
||||
|
||||
thread_local const val Uint8Array = val::global("Uint8Array");
|
||||
|
||||
val encode(std::string img, int width, int height, WebPConfig config) {
|
||||
auto img_in = (uint8_t*)img.c_str();
|
||||
|
||||
// A lot of this is duplicated from Encode in picture_enc.c
|
||||
WebPPicture pic;
|
||||
WebPMemoryWriter wrt;
|
||||
int ok;
|
||||
|
||||
if (!WebPPictureInit(&pic)) {
|
||||
// shouldn't happen, except if system installation is broken
|
||||
return val::null();
|
||||
}
|
||||
|
||||
// Allow quality to go higher than 0.
|
||||
config.qmax = 100;
|
||||
|
||||
// Only use use_argb if we really need it, as it's slower.
|
||||
pic.use_argb = config.lossless || config.use_sharp_yuv || config.preprocessing > 0;
|
||||
pic.width = width;
|
||||
pic.height = height;
|
||||
pic.writer = WebPMemoryWrite;
|
||||
pic.custom_ptr = &wrt;
|
||||
|
||||
WebPMemoryWriterInit(&wrt);
|
||||
|
||||
ok = WebPPictureImportRGBA(&pic, img_in, width * 4) && WebPEncode(&config, &pic);
|
||||
WebPPictureFree(&pic);
|
||||
val js_result = ok ? Uint8Array.new_(typed_memory_view(wrt.size, wrt.mem)) : val::null();
|
||||
WebPMemoryWriterClear(&wrt);
|
||||
return js_result;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(my_module) {
|
||||
enum_<WebPImageHint>("WebPImageHint")
|
||||
.value("WEBP_HINT_DEFAULT", WebPImageHint::WEBP_HINT_DEFAULT)
|
||||
.value("WEBP_HINT_PICTURE", WebPImageHint::WEBP_HINT_PICTURE)
|
||||
.value("WEBP_HINT_PHOTO", WebPImageHint::WEBP_HINT_PHOTO)
|
||||
.value("WEBP_HINT_GRAPH", WebPImageHint::WEBP_HINT_GRAPH);
|
||||
|
||||
value_object<WebPConfig>("WebPConfig")
|
||||
.field("lossless", &WebPConfig::lossless)
|
||||
.field("quality", &WebPConfig::quality)
|
||||
.field("method", &WebPConfig::method)
|
||||
.field("image_hint", &WebPConfig::image_hint)
|
||||
.field("target_size", &WebPConfig::target_size)
|
||||
.field("target_PSNR", &WebPConfig::target_PSNR)
|
||||
.field("segments", &WebPConfig::segments)
|
||||
.field("sns_strength", &WebPConfig::sns_strength)
|
||||
.field("filter_strength", &WebPConfig::filter_strength)
|
||||
.field("filter_sharpness", &WebPConfig::filter_sharpness)
|
||||
.field("filter_type", &WebPConfig::filter_type)
|
||||
.field("autofilter", &WebPConfig::autofilter)
|
||||
.field("alpha_compression", &WebPConfig::alpha_compression)
|
||||
.field("alpha_filtering", &WebPConfig::alpha_filtering)
|
||||
.field("alpha_quality", &WebPConfig::alpha_quality)
|
||||
.field("pass", &WebPConfig::pass)
|
||||
.field("show_compressed", &WebPConfig::show_compressed)
|
||||
.field("preprocessing", &WebPConfig::preprocessing)
|
||||
.field("partitions", &WebPConfig::partitions)
|
||||
.field("partition_limit", &WebPConfig::partition_limit)
|
||||
.field("emulate_jpeg_size", &WebPConfig::emulate_jpeg_size)
|
||||
.field("low_memory", &WebPConfig::low_memory)
|
||||
.field("near_lossless", &WebPConfig::near_lossless)
|
||||
.field("exact", &WebPConfig::exact)
|
||||
.field("use_delta_palette", &WebPConfig::use_delta_palette)
|
||||
.field("use_sharp_yuv", &WebPConfig::use_sharp_yuv);
|
||||
|
||||
function("version", &version);
|
||||
function("encode", &encode);
|
||||
}
|
||||
42
codecs/webp/wasm_build/base/enc/webp_enc.d.ts
vendored
Normal file
42
codecs/webp/wasm_build/base/enc/webp_enc.d.ts
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
export interface EncodeOptions {
|
||||
quality: number;
|
||||
target_size: number;
|
||||
target_PSNR: number;
|
||||
method: number;
|
||||
sns_strength: number;
|
||||
filter_strength: number;
|
||||
filter_sharpness: number;
|
||||
filter_type: number;
|
||||
partitions: number;
|
||||
segments: number;
|
||||
pass: number;
|
||||
show_compressed: number;
|
||||
preprocessing: number;
|
||||
autofilter: number;
|
||||
partition_limit: number;
|
||||
alpha_compression: number;
|
||||
alpha_filtering: number;
|
||||
alpha_quality: number;
|
||||
lossless: number;
|
||||
exact: number;
|
||||
image_hint: number;
|
||||
emulate_jpeg_size: number;
|
||||
thread_level: number;
|
||||
low_memory: number;
|
||||
near_lossless: number;
|
||||
use_delta_palette: number;
|
||||
use_sharp_yuv: number;
|
||||
}
|
||||
|
||||
export interface WebPModule extends EmscriptenWasm.Module {
|
||||
encode(
|
||||
data: BufferSource,
|
||||
width: number,
|
||||
height: number,
|
||||
options: EncodeOptions,
|
||||
): Uint8Array | null;
|
||||
}
|
||||
|
||||
declare var moduleFactory: EmscriptenWasm.ModuleFactory<WebPModule>;
|
||||
|
||||
export default moduleFactory;
|
||||
16
codecs/webp/wasm_build/base/enc/webp_enc.js
generated
Normal file
16
codecs/webp/wasm_build/base/enc/webp_enc.js
generated
Normal file
File diff suppressed because one or more lines are too long
BIN
codecs/webp/wasm_build/base/enc/webp_enc.wasm
Executable file
BIN
codecs/webp/wasm_build/base/enc/webp_enc.wasm
Executable file
Binary file not shown.
1
codecs/webp/wasm_build/base/enc/webp_enc_simd.d.ts
vendored
Normal file
1
codecs/webp/wasm_build/base/enc/webp_enc_simd.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './webp_enc.js';
|
||||
18
codecs/webp/wasm_build/simd/dec/README.md
Normal file
18
codecs/webp/wasm_build/simd/dec/README.md
Normal file
@@ -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
codecs/webp/wasm_build/simd/dec/example.html
Normal file
20
codecs/webp/wasm_build/simd/dec/example.html
Normal file
@@ -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
codecs/webp/wasm_build/simd/dec/webp_dec.cpp
Normal file
29
codecs/webp/wasm_build/simd/dec/webp_dec.cpp
Normal file
@@ -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
codecs/webp/wasm_build/simd/dec/webp_dec.d.ts
vendored
Normal file
7
codecs/webp/wasm_build/simd/dec/webp_dec.d.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface WebPModule extends EmscriptenWasm.Module {
|
||||
decode(data: BufferSource): ImageData | null;
|
||||
}
|
||||
|
||||
declare var moduleFactory: EmscriptenWasm.ModuleFactory<WebPModule>;
|
||||
|
||||
export default moduleFactory;
|
||||
16
codecs/webp/wasm_build/simd/dec/webp_dec.js
generated
Normal file
16
codecs/webp/wasm_build/simd/dec/webp_dec.js
generated
Normal file
File diff suppressed because one or more lines are too long
BIN
codecs/webp/wasm_build/simd/dec/webp_dec.wasm
Executable file
BIN
codecs/webp/wasm_build/simd/dec/webp_dec.wasm
Executable file
Binary file not shown.
22
codecs/webp/wasm_build/simd/enc/README.md
Normal file
22
codecs/webp/wasm_build/simd/enc/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# WebP encoder
|
||||
|
||||
- Source: <https://github.com/webmproject/libwebp>
|
||||
- Version: v1.0.2
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Docker
|
||||
|
||||
## Example
|
||||
|
||||
See `example.html`
|
||||
|
||||
## API
|
||||
|
||||
### `int version()`
|
||||
|
||||
Returns the version of libwebp as a number. va.b.c is encoded as 0x0a0b0c
|
||||
|
||||
### `UInt8Array encode(uint8_t* image_buffer, int image_width, int image_height, WebPConfig config)`
|
||||
|
||||
Encodes the given image with given dimension to WebP.
|
||||
58
codecs/webp/wasm_build/simd/enc/example.html
Normal file
58
codecs/webp/wasm_build/simd/enc/example.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<!doctype html>
|
||||
<script src='webp_enc.js'></script>
|
||||
<script>
|
||||
async function loadImage(src) {
|
||||
// Load image
|
||||
const img = document.createElement('img');
|
||||
img.src = src;
|
||||
await new Promise(resolve => img.onload = resolve);
|
||||
// Make canvas same size as image
|
||||
const canvas = document.createElement('canvas');
|
||||
[canvas.width, canvas.height] = [img.width, img.height];
|
||||
// Draw image onto canvas
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(img, 0, 0);
|
||||
return ctx.getImageData(0, 0, img.width, img.height);
|
||||
}
|
||||
|
||||
webp_enc().then(async module => {
|
||||
console.log('Version:', module.version().toString(16));
|
||||
const image = await loadImage('../../example.png');
|
||||
const result = module.encode(image.data, image.width, image.height, {
|
||||
quality: 75,
|
||||
target_size: 0,
|
||||
target_PSNR: 0,
|
||||
method: 4,
|
||||
sns_strength: 50,
|
||||
filter_strength: 60,
|
||||
filter_sharpness: 0,
|
||||
filter_type: 1,
|
||||
partitions: 0,
|
||||
segments: 4,
|
||||
pass: 1,
|
||||
show_compressed: 0,
|
||||
preprocessing: 0,
|
||||
autofilter: 0,
|
||||
partition_limit: 0,
|
||||
alpha_compression: 1,
|
||||
alpha_filtering: 1,
|
||||
alpha_quality: 100,
|
||||
lossless: 0,
|
||||
exact: 0,
|
||||
image_hint: 0,
|
||||
emulate_jpeg_size: 0,
|
||||
thread_level: 0,
|
||||
low_memory: 0,
|
||||
near_lossless: 100,
|
||||
use_delta_palette: 0,
|
||||
use_sharp_yuv: 0,
|
||||
});
|
||||
console.log('size', result.length);
|
||||
const blob = new Blob([result], {type: 'image/webp'});
|
||||
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
const img = document.createElement('img');
|
||||
img.src = blobURL;
|
||||
document.body.appendChild(img);
|
||||
});
|
||||
</script>
|
||||
85
codecs/webp/wasm_build/simd/enc/webp_enc.cpp
Normal file
85
codecs/webp/wasm_build/simd/enc/webp_enc.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdexcept>
|
||||
#include "webp/encode.h"
|
||||
|
||||
using namespace emscripten;
|
||||
|
||||
int version() {
|
||||
return WebPGetEncoderVersion();
|
||||
}
|
||||
|
||||
thread_local const val Uint8Array = val::global("Uint8Array");
|
||||
|
||||
val encode(std::string img, int width, int height, WebPConfig config) {
|
||||
auto img_in = (uint8_t*)img.c_str();
|
||||
|
||||
// A lot of this is duplicated from Encode in picture_enc.c
|
||||
WebPPicture pic;
|
||||
WebPMemoryWriter wrt;
|
||||
int ok;
|
||||
|
||||
if (!WebPPictureInit(&pic)) {
|
||||
// shouldn't happen, except if system installation is broken
|
||||
return val::null();
|
||||
}
|
||||
|
||||
// Allow quality to go higher than 0.
|
||||
config.qmax = 100;
|
||||
|
||||
// Only use use_argb if we really need it, as it's slower.
|
||||
pic.use_argb = config.lossless || config.use_sharp_yuv || config.preprocessing > 0;
|
||||
pic.width = width;
|
||||
pic.height = height;
|
||||
pic.writer = WebPMemoryWrite;
|
||||
pic.custom_ptr = &wrt;
|
||||
|
||||
WebPMemoryWriterInit(&wrt);
|
||||
|
||||
ok = WebPPictureImportRGBA(&pic, img_in, width * 4) && WebPEncode(&config, &pic);
|
||||
WebPPictureFree(&pic);
|
||||
val js_result = ok ? Uint8Array.new_(typed_memory_view(wrt.size, wrt.mem)) : val::null();
|
||||
WebPMemoryWriterClear(&wrt);
|
||||
return js_result;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_BINDINGS(my_module) {
|
||||
enum_<WebPImageHint>("WebPImageHint")
|
||||
.value("WEBP_HINT_DEFAULT", WebPImageHint::WEBP_HINT_DEFAULT)
|
||||
.value("WEBP_HINT_PICTURE", WebPImageHint::WEBP_HINT_PICTURE)
|
||||
.value("WEBP_HINT_PHOTO", WebPImageHint::WEBP_HINT_PHOTO)
|
||||
.value("WEBP_HINT_GRAPH", WebPImageHint::WEBP_HINT_GRAPH);
|
||||
|
||||
value_object<WebPConfig>("WebPConfig")
|
||||
.field("lossless", &WebPConfig::lossless)
|
||||
.field("quality", &WebPConfig::quality)
|
||||
.field("method", &WebPConfig::method)
|
||||
.field("image_hint", &WebPConfig::image_hint)
|
||||
.field("target_size", &WebPConfig::target_size)
|
||||
.field("target_PSNR", &WebPConfig::target_PSNR)
|
||||
.field("segments", &WebPConfig::segments)
|
||||
.field("sns_strength", &WebPConfig::sns_strength)
|
||||
.field("filter_strength", &WebPConfig::filter_strength)
|
||||
.field("filter_sharpness", &WebPConfig::filter_sharpness)
|
||||
.field("filter_type", &WebPConfig::filter_type)
|
||||
.field("autofilter", &WebPConfig::autofilter)
|
||||
.field("alpha_compression", &WebPConfig::alpha_compression)
|
||||
.field("alpha_filtering", &WebPConfig::alpha_filtering)
|
||||
.field("alpha_quality", &WebPConfig::alpha_quality)
|
||||
.field("pass", &WebPConfig::pass)
|
||||
.field("show_compressed", &WebPConfig::show_compressed)
|
||||
.field("preprocessing", &WebPConfig::preprocessing)
|
||||
.field("partitions", &WebPConfig::partitions)
|
||||
.field("partition_limit", &WebPConfig::partition_limit)
|
||||
.field("emulate_jpeg_size", &WebPConfig::emulate_jpeg_size)
|
||||
.field("low_memory", &WebPConfig::low_memory)
|
||||
.field("near_lossless", &WebPConfig::near_lossless)
|
||||
.field("exact", &WebPConfig::exact)
|
||||
.field("use_delta_palette", &WebPConfig::use_delta_palette)
|
||||
.field("use_sharp_yuv", &WebPConfig::use_sharp_yuv);
|
||||
|
||||
function("version", &version);
|
||||
function("encode", &encode);
|
||||
}
|
||||
42
codecs/webp/wasm_build/simd/enc/webp_enc.d.ts
vendored
Normal file
42
codecs/webp/wasm_build/simd/enc/webp_enc.d.ts
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
export interface EncodeOptions {
|
||||
quality: number;
|
||||
target_size: number;
|
||||
target_PSNR: number;
|
||||
method: number;
|
||||
sns_strength: number;
|
||||
filter_strength: number;
|
||||
filter_sharpness: number;
|
||||
filter_type: number;
|
||||
partitions: number;
|
||||
segments: number;
|
||||
pass: number;
|
||||
show_compressed: number;
|
||||
preprocessing: number;
|
||||
autofilter: number;
|
||||
partition_limit: number;
|
||||
alpha_compression: number;
|
||||
alpha_filtering: number;
|
||||
alpha_quality: number;
|
||||
lossless: number;
|
||||
exact: number;
|
||||
image_hint: number;
|
||||
emulate_jpeg_size: number;
|
||||
thread_level: number;
|
||||
low_memory: number;
|
||||
near_lossless: number;
|
||||
use_delta_palette: number;
|
||||
use_sharp_yuv: number;
|
||||
}
|
||||
|
||||
export interface WebPModule extends EmscriptenWasm.Module {
|
||||
encode(
|
||||
data: BufferSource,
|
||||
width: number,
|
||||
height: number,
|
||||
options: EncodeOptions,
|
||||
): Uint8Array | null;
|
||||
}
|
||||
|
||||
declare var moduleFactory: EmscriptenWasm.ModuleFactory<WebPModule>;
|
||||
|
||||
export default moduleFactory;
|
||||
16
codecs/webp/wasm_build/simd/enc/webp_enc.js
generated
Normal file
16
codecs/webp/wasm_build/simd/enc/webp_enc.js
generated
Normal file
File diff suppressed because one or more lines are too long
BIN
codecs/webp/wasm_build/simd/enc/webp_enc.wasm
Executable file
BIN
codecs/webp/wasm_build/simd/enc/webp_enc.wasm
Executable file
Binary file not shown.
1
codecs/webp/wasm_build/simd/enc/webp_enc_simd.d.ts
vendored
Normal file
1
codecs/webp/wasm_build/simd/enc/webp_enc_simd.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './webp_enc.js';
|
||||
10
nix/Dockerfile
Normal file
10
nix/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM nixos/nix:2.24.5
|
||||
|
||||
RUN <<EOF
|
||||
cat >> /etc/nix/nix.conf << EOL
|
||||
experimental-features = nix-command flakes
|
||||
EOL
|
||||
EOF
|
||||
|
||||
WORKDIR /app
|
||||
CMD ["nix", "run", ".#updateRepoBinaries"]
|
||||
75
nix/rust-helpers/default.nix
Normal file
75
nix/rust-helpers/default.nix
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
rustPlatform,
|
||||
jq,
|
||||
rsync,
|
||||
lib,
|
||||
stdenv,
|
||||
# openssl,
|
||||
pkg-config,
|
||||
fenix,
|
||||
}:
|
||||
{
|
||||
buildRustPackage =
|
||||
{
|
||||
target,
|
||||
src,
|
||||
cargoLock ? {
|
||||
lockFile = "${src}/Cargo.lock";
|
||||
},
|
||||
release ? true,
|
||||
...
|
||||
}@args:
|
||||
let
|
||||
# Setup a toolchain for the the host system targeting `target`.
|
||||
toolchain =
|
||||
let
|
||||
inherit (fenix) stable targets combine;
|
||||
in
|
||||
combine [
|
||||
stable.rustc
|
||||
stable.cargo
|
||||
targets.${target}.stable.rust-std
|
||||
];
|
||||
|
||||
# Create `vendor` folder with all dependencies.
|
||||
vendoredDependencies = rustPlatform.importCargoLock cargoLock;
|
||||
|
||||
rustcTargetDir = "target/${target}/${if release then "release" else "debug"}";
|
||||
in
|
||||
stdenv.mkDerivation (
|
||||
(removeAttrs args [ "cargoLock" ])
|
||||
// {
|
||||
nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [
|
||||
toolchain
|
||||
jq
|
||||
rsync
|
||||
pkg-config
|
||||
# (lib.getDev openssl)
|
||||
];
|
||||
buildInputs = [
|
||||
# openssl
|
||||
];
|
||||
dontConfigure = true;
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
cargo build \
|
||||
--config 'source.crates-io.replace-with="vendored-sources"' \
|
||||
--config 'source.vendored-sources.directory="${vendoredDependencies}"' \
|
||||
--offline \
|
||||
--target ${target} ${if release then "-r" else ""}
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
installPhase = ''
|
||||
runHook preInstall;
|
||||
mkdir -p $out
|
||||
|
||||
find ${rustcTargetDir} -type f -maxdepth 1 | \
|
||||
xargs -I ___X -n1 cp ___X $out
|
||||
|
||||
runHook postInstall;
|
||||
'';
|
||||
}
|
||||
);
|
||||
}
|
||||
30
nix/squoosh-cxx-builder/default.nix
Normal file
30
nix/squoosh-cxx-builder/default.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
pkgs,
|
||||
stdenv,
|
||||
runCommand,
|
||||
}:
|
||||
{
|
||||
name,
|
||||
nativeBuildInputs ? [ ],
|
||||
encoder ? "enc",
|
||||
decoder ? "dec",
|
||||
...
|
||||
}@args:
|
||||
|
||||
stdenv.mkDerivation (
|
||||
final:
|
||||
args
|
||||
// {
|
||||
inherit name;
|
||||
nativeBuildInputs = [ pkgs.emscripten ] ++ nativeBuildInputs;
|
||||
buildPhase = ''
|
||||
export HOME=$TMPDIR
|
||||
emmake make -j$(nproc)
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
${if (encoder != null) then "cp -r ${encoder} $out" else ""}
|
||||
${if (decoder != null) then "cp -r ${decoder} $out" else ""}
|
||||
'';
|
||||
}
|
||||
)
|
||||
36
nix/squoosh-helpers/default.nix
Normal file
36
nix/squoosh-helpers/default.nix
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
coreutils,
|
||||
rsync,
|
||||
writeShellScriptBin,
|
||||
lib,
|
||||
}:
|
||||
let
|
||||
suffixAttrNames =
|
||||
suffix: attrs: lib.mapAttrs' (name: val: lib.nameValuePair "${name}${suffix}" val) attrs;
|
||||
in
|
||||
{
|
||||
inherit suffixAttrNames;
|
||||
|
||||
mkRepoBinaryUpdater =
|
||||
flake:
|
||||
let
|
||||
script = writeShellScriptBin "updateRepoBinaries.sh" ''
|
||||
${coreutils}/bin/mkdir -p wasm_build
|
||||
${rsync}/bin/rsync --chmod=u+w -r ${flake.packages.default}/* wasm_build/
|
||||
'';
|
||||
in
|
||||
lib.recursiveUpdate flake {
|
||||
apps.updateRepoBinaries = {
|
||||
type = "app";
|
||||
program = "${script}/bin/updateRepoBinaries.sh";
|
||||
};
|
||||
};
|
||||
|
||||
forAllVariants =
|
||||
{ builder, variants }:
|
||||
lib.lists.foldl (acc: v: acc // v) { } (
|
||||
lib.mapAttrsToList (
|
||||
variantName: value: suffixAttrNames "-${variantName}" (builder variantName value)
|
||||
) variants
|
||||
);
|
||||
}
|
||||
78
nix/squoosh-rust-builder/default.nix
Normal file
78
nix/squoosh-rust-builder/default.nix
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
pkgs,
|
||||
fenix,
|
||||
wasm-bindgen ? pkgs.callPackage (import ../wasm-bindgen) { },
|
||||
rust-helpers ? pkgs.callPackage (import ../rust-helpers) { inherit fenix; },
|
||||
binaryen,
|
||||
stdenv,
|
||||
}:
|
||||
let
|
||||
inherit (rust-helpers) buildRustPackage;
|
||||
in
|
||||
|
||||
{
|
||||
name,
|
||||
src,
|
||||
cargoLock ? {
|
||||
lockFile = "${src}/Cargo.lock";
|
||||
},
|
||||
wasmBindgen ? {
|
||||
sha256 = "";
|
||||
},
|
||||
...
|
||||
}@args:
|
||||
let
|
||||
codecBuild = buildRustPackage {
|
||||
inherit src cargoLock;
|
||||
name = "${name}-codec";
|
||||
target = "wasm32-unknown-unknown";
|
||||
};
|
||||
|
||||
wasm-bindgen-bin = wasm-bindgen.buildFromCargoLock {
|
||||
inherit cargoLock;
|
||||
sha256 = wasmBindgen.sha256;
|
||||
};
|
||||
in
|
||||
if wasmBindgen != null then
|
||||
stdenv.mkDerivation (
|
||||
(removeAttrs args [
|
||||
"cargoLock"
|
||||
"wasmBindgen"
|
||||
])
|
||||
// {
|
||||
inherit codecBuild;
|
||||
dontConfigure = true;
|
||||
nativeBuildInputs = [ wasm-bindgen-bin ];
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
wasm-bindgen --target web --out-dir $out $codecBuild/*.wasm
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
dontInstall = true;
|
||||
}
|
||||
)
|
||||
else
|
||||
stdenv.mkDerivation (
|
||||
(removeAttrs args [
|
||||
"cargoLock"
|
||||
"wasmBindgen"
|
||||
])
|
||||
// {
|
||||
inherit codecBuild;
|
||||
dontConfigure = true;
|
||||
nativeBuildInputs = [ binaryen ];
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
wasm-opt -O3 --strip -o optimized.wasm $codecBuild/*.wasm
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
cp optimized.wasm $out
|
||||
'';
|
||||
}
|
||||
)
|
||||
59
nix/wasm-bindgen/default.nix
Normal file
59
nix/wasm-bindgen/default.nix
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
lib,
|
||||
fetchCrate,
|
||||
rustPlatform,
|
||||
curl,
|
||||
stdenv,
|
||||
openssl_1_1,
|
||||
pkg-config,
|
||||
darwin,
|
||||
}:
|
||||
rec {
|
||||
build =
|
||||
{ version, sha256 }:
|
||||
let
|
||||
src = fetchCrate {
|
||||
pname = "wasm-bindgen-cli";
|
||||
inherit version sha256;
|
||||
};
|
||||
|
||||
cargoLock = {
|
||||
lockFile = "${src}/Cargo.lock";
|
||||
};
|
||||
in
|
||||
rustPlatform.buildRustPackage {
|
||||
name = "wasm-bindgen-cli";
|
||||
inherit src cargoLock;
|
||||
nativeBuildInputs = [
|
||||
pkg-config
|
||||
];
|
||||
buildInputs = [
|
||||
openssl_1_1
|
||||
] ++ lib.optionals stdenv.isDarwin [
|
||||
darwin.apple_sdk.frameworks.IOKit
|
||||
];
|
||||
|
||||
doCheck = false;
|
||||
};
|
||||
|
||||
buildFromCargoLock =
|
||||
{ cargoLock, sha256 }:
|
||||
assert (cargoLock.lockFile or null == null) != (cargoLock.lockFileContents or null == null);
|
||||
let
|
||||
lockFileContents =
|
||||
if cargoLock.lockFile != null then
|
||||
builtins.readFile cargoLock.lockFile
|
||||
else
|
||||
cargoLock.lockFileContents;
|
||||
|
||||
parsedLockFile = builtins.fromTOML lockFileContents;
|
||||
|
||||
wasm-bindgen-version =
|
||||
(lib.lists.findFirst (x: x.name == "wasm-bindgen") null parsedLockFile.package).version;
|
||||
in
|
||||
assert wasm-bindgen-version != null;
|
||||
build {
|
||||
inherit sha256;
|
||||
version = wasm-bindgen-version;
|
||||
};
|
||||
}
|
||||
252
package-lock.json
generated
252
package-lock.json
generated
@@ -12,6 +12,7 @@
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.1.0",
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@surma/rollup-plugin-off-main-thread": "^2.2.2",
|
||||
"@types/dedent": "^0.7.0",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
@@ -149,6 +150,70 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/set-array": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/source-map": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
|
||||
@@ -245,6 +310,39 @@
|
||||
"magic-string": "^0.25.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-terser": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
|
||||
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"serialize-javascript": "^6.0.1",
|
||||
"smob": "^1.0.0",
|
||||
"terser": "^5.17.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^2.0.0||^3.0.0||^4.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-terser/node_modules/serialize-javascript": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
|
||||
@@ -404,6 +502,19 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.12.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aggregate-error": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
|
||||
@@ -760,10 +871,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
|
||||
"dev": true
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/builtin-modules": {
|
||||
"version": "3.2.0",
|
||||
@@ -7884,6 +7996,13 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/smob": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
|
||||
"integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -7894,10 +8013,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.19",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
|
||||
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
@@ -8408,14 +8528,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.3.1.tgz",
|
||||
"integrity": "sha512-yD80f4hdwCWTH5mojzxe1q8bN1oJbsK/vfJGLcPZM/fl+/jItIVNKhFIHqqR71OipFWMLgj3Kc+GIp6CeIqfnA==",
|
||||
"version": "5.31.4",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.4.tgz",
|
||||
"integrity": "sha512-3OU03GgblDgu0g+sdnsVzhBPxnjV+WJuMmocN1qBBZDQ3ia7jZQSAkePeKbPlYAejGXUTYe1CmSaUeV51mvaIw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
"commander": "^2.20.0",
|
||||
"source-map": "~0.6.1",
|
||||
"source-map-support": "~0.5.12"
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
"bin": {
|
||||
"terser": "bin/terser"
|
||||
@@ -8756,6 +8878,55 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@jridgewell/gen-mapping": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
|
||||
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/set-array": "^1.2.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
"@jridgewell/trace-mapping": "^0.3.24"
|
||||
}
|
||||
},
|
||||
"@jridgewell/resolve-uri": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
|
||||
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
|
||||
"dev": true
|
||||
},
|
||||
"@jridgewell/set-array": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
|
||||
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
|
||||
"dev": true
|
||||
},
|
||||
"@jridgewell/source-map": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
|
||||
"integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25"
|
||||
}
|
||||
},
|
||||
"@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@jridgewell/trace-mapping": {
|
||||
"version": "0.3.25",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
|
||||
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz",
|
||||
@@ -8841,6 +9012,28 @@
|
||||
"magic-string": "^0.25.7"
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-terser": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz",
|
||||
"integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"serialize-javascript": "^6.0.1",
|
||||
"smob": "^1.0.0",
|
||||
"terser": "^5.17.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"serialize-javascript": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@rollup/pluginutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
|
||||
@@ -8986,6 +9179,12 @@
|
||||
"negotiator": "0.6.2"
|
||||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "8.12.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
|
||||
"integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
|
||||
"dev": true
|
||||
},
|
||||
"aggregate-error": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
|
||||
@@ -9274,9 +9473,9 @@
|
||||
}
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"builtin-modules": {
|
||||
@@ -15195,6 +15394,12 @@
|
||||
"is-fullwidth-code-point": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"smob": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
|
||||
"integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==",
|
||||
"dev": true
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -15202,9 +15407,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.5.19",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
|
||||
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
@@ -15625,14 +15830,15 @@
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.3.1.tgz",
|
||||
"integrity": "sha512-yD80f4hdwCWTH5mojzxe1q8bN1oJbsK/vfJGLcPZM/fl+/jItIVNKhFIHqqR71OipFWMLgj3Kc+GIp6CeIqfnA==",
|
||||
"version": "5.31.4",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.31.4.tgz",
|
||||
"integrity": "sha512-3OU03GgblDgu0g+sdnsVzhBPxnjV+WJuMmocN1qBBZDQ3ia7jZQSAkePeKbPlYAejGXUTYe1CmSaUeV51mvaIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.8.2",
|
||||
"commander": "^2.20.0",
|
||||
"source-map": "~0.6.1",
|
||||
"source-map-support": "~0.5.12"
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.1.0",
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@surma/rollup-plugin-off-main-thread": "^2.2.2",
|
||||
"@types/dedent": "^0.7.0",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
@@ -43,11 +44,10 @@
|
||||
"preact-render-to-string": "^5.1.11",
|
||||
"prettier": "^2.4.1",
|
||||
"rollup": "^2.38.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"serve": "^11.3.2",
|
||||
"typescript": "^4.4.4",
|
||||
"which": "^2.0.2",
|
||||
"wasm-feature-detect": "^1.2.11"
|
||||
"wasm-feature-detect": "^1.2.11",
|
||||
"which": "^2.0.2"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,css,json,md,ts,tsx}": "prettier --write",
|
||||
|
||||
@@ -15,7 +15,7 @@ import { promises as fsp } from 'fs';
|
||||
import del from 'del';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import terser from '@rollup/plugin-terser';
|
||||
import OMT from '@surma/rollup-plugin-off-main-thread';
|
||||
import replace from '@rollup/plugin-replace';
|
||||
import { importMetaAssets } from '@web/rollup-plugin-import-meta-assets';
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import type { WebPModule } from 'codecs/webp/dec/webp_dec';
|
||||
import type { WebPModule } from 'codecs/webp/wasm_build/base/dec/webp_dec';
|
||||
import { initEmscriptenModule, blobToArrayBuffer } from 'features/worker-utils';
|
||||
|
||||
let emscriptenModule: Promise<WebPModule>;
|
||||
|
||||
export default async function decode(blob: Blob): Promise<ImageData> {
|
||||
if (!emscriptenModule) {
|
||||
const decoder = await import('codecs/webp/dec/webp_dec');
|
||||
const decoder = await import('codecs/webp/wasm_build/base/dec/webp_dec');
|
||||
emscriptenModule = initEmscriptenModule(decoder.default);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
import {
|
||||
EncodeOptions,
|
||||
MozJpegColorSpace,
|
||||
} from 'codecs/mozjpeg/enc/mozjpeg_enc';
|
||||
} from 'codecs/mozjpeg/wasm_build/enc/mozjpeg_enc';
|
||||
export { EncodeOptions, MozJpegColorSpace };
|
||||
|
||||
export const label = 'MozJPEG';
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import mozjpeg_enc, { MozJPEGModule } from 'codecs/mozjpeg/enc/mozjpeg_enc';
|
||||
import mozjpeg_enc, {
|
||||
MozJPEGModule,
|
||||
} from 'codecs/mozjpeg/wasm_build/enc/mozjpeg_enc';
|
||||
import { EncodeOptions } from '../shared/meta';
|
||||
import { initEmscriptenModule } from 'features/worker-utils';
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import type { EncodeOptions } from 'codecs/webp/enc/webp_enc';
|
||||
import type { EncodeOptions } from 'codecs/webp/wasm_build/base/enc/webp_enc';
|
||||
|
||||
export { EncodeOptions };
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import type { WebPModule } from 'codecs/webp/enc/webp_enc';
|
||||
import type { WebPModule } from 'codecs/webp/wasm_build/base/enc/webp_enc';
|
||||
import type { EncodeOptions } from '../shared/meta';
|
||||
|
||||
import { initEmscriptenModule } from 'features/worker-utils';
|
||||
@@ -20,10 +20,12 @@ let emscriptenModule: Promise<WebPModule>;
|
||||
|
||||
async function init() {
|
||||
if (await simd()) {
|
||||
const webpEncoder = await import('codecs/webp/enc/webp_enc_simd');
|
||||
const webpEncoder = await import(
|
||||
'codecs/webp/wasm_build/simd/enc/webp_enc'
|
||||
);
|
||||
return initEmscriptenModule(webpEncoder.default);
|
||||
}
|
||||
const webpEncoder = await import('codecs/webp/enc/webp_enc');
|
||||
const webpEncoder = await import('codecs/webp/wasm_build/base/enc/webp_enc');
|
||||
return initEmscriptenModule(webpEncoder.default);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import wasmUrl from 'url:codecs/rotate/rotate.wasm';
|
||||
import wasmUrl from 'url:codecs/rotate/wasm_build/optimized.wasm';
|
||||
import { Options } from '../shared/meta';
|
||||
|
||||
export interface RotateModuleInstance {
|
||||
|
||||
@@ -25,7 +25,7 @@ import * as featuresWorker from 'entry-data:../features-worker';
|
||||
|
||||
// Decoders (some are feature detected)
|
||||
import * as avifDec from 'entry-data:codecs/avif/dec/avif_dec';
|
||||
import * as webpDec from 'entry-data:codecs/webp/dec/webp_dec';
|
||||
import * as webpDec from 'entry-data:codecs/webp/wasm_build/base/dec/webp_dec';
|
||||
|
||||
// AVIF
|
||||
import * as avifEncMt from 'entry-data:codecs/avif/enc/avif_enc_mt';
|
||||
@@ -41,8 +41,8 @@ import * as oxiMt from 'entry-data:codecs/oxipng/pkg-parallel/squoosh_oxipng';
|
||||
import * as oxi from 'entry-data:codecs/oxipng/pkg/squoosh_oxipng';
|
||||
|
||||
// WebP
|
||||
import * as webpEncSimd from 'entry-data:codecs/webp/enc/webp_enc_simd';
|
||||
import * as webpEnc from 'entry-data:codecs/webp/enc/webp_enc';
|
||||
import * as webpEncSimd from 'entry-data:codecs/webp/wasm_build/simd/enc/webp_enc';
|
||||
import * as webpEnc from 'entry-data:codecs/webp/wasm_build/base/enc/webp_enc';
|
||||
|
||||
// WP2
|
||||
import * as wp2EncMtSimd from 'entry-data:codecs/wp2/enc/wp2_enc_mt_simd';
|
||||
|
||||
Reference in New Issue
Block a user