forked from external-repos/squoosh
Mozjpeg opts (#140)
* Switching to embind * Adding options to mozjpeg wasm * Updating packages * Ditching enum - causing more problems than it's worth * Adding mozjpeg options UI * Forgot about this enum * Bools just work
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<!doctype html>
|
||||
<script src='mozjpeg_enc.js'></script>
|
||||
<script>
|
||||
const Module = mozjpeg_enc();
|
||||
const module = mozjpeg_enc();
|
||||
|
||||
async function loadImage(src) {
|
||||
// Load image
|
||||
@@ -17,27 +17,32 @@
|
||||
return ctx.getImageData(0, 0, img.width, img.height);
|
||||
}
|
||||
|
||||
Module.onRuntimeInitialized = async _ => {
|
||||
const api = {
|
||||
version: Module.cwrap('version', 'number', []),
|
||||
create_buffer: Module.cwrap('create_buffer', 'number', ['number', 'number']),
|
||||
destroy_buffer: Module.cwrap('destroy_buffer', '', ['number']),
|
||||
encode: Module.cwrap('encode', '', ['number', 'number', 'number', 'number']),
|
||||
free_result: Module.cwrap('free_result', '', ['number']),
|
||||
get_result_pointer: Module.cwrap('get_result_pointer', 'number', []),
|
||||
get_result_size: Module.cwrap('get_result_size', 'number', []),
|
||||
};
|
||||
console.log('Version:', api.version().toString(16));
|
||||
module.onRuntimeInitialized = async _ => {
|
||||
console.log('Version:', module.version().toString(16));
|
||||
const image = await loadImage('../example.png');
|
||||
const p = api.create_buffer(image.width, image.height);
|
||||
Module.HEAP8.set(image.data, p);
|
||||
api.encode(p, image.width, image.height, 2);
|
||||
const resultPointer = api.get_result_pointer();
|
||||
const resultSize = api.get_result_size();
|
||||
const resultView = new Uint8Array(Module.HEAP8.buffer, resultPointer, resultSize);
|
||||
const p = module.create_buffer(image.width, image.height);
|
||||
module.HEAP8.set(image.data, p);
|
||||
module.encode(p, image.width, image.height, {
|
||||
quality: 40,
|
||||
baseline: false,
|
||||
arithmetic: false,
|
||||
progressive: true,
|
||||
optimize_coding: true,
|
||||
smoothing: 0,
|
||||
color_space: 3,
|
||||
quant_table: 3,
|
||||
trellis_multipass: true,
|
||||
trellis_opt_zero: true,
|
||||
trellis_opt_table: true,
|
||||
trellis_loops: 1,
|
||||
});
|
||||
const resultPointer = module.get_result_pointer();
|
||||
const resultSize = module.get_result_size();
|
||||
console.log('size', resultSize);
|
||||
const resultView = new Uint8Array(module.HEAP8.buffer, resultPointer, resultSize);
|
||||
const result = new Uint8Array(resultView);
|
||||
api.free_result(resultPointer);
|
||||
api.destroy_buffer(p);
|
||||
module.free_result();
|
||||
module.destroy_buffer(p);
|
||||
|
||||
const blob = new Blob([result], {type: 'image/jpeg'});
|
||||
const blobURL = URL.createObjectURL(blob);
|
||||
|
||||
@@ -4,14 +4,33 @@
|
||||
#include <stdio.h>
|
||||
#include <setjmp.h>
|
||||
#include <string.h>
|
||||
#include "jpeglib.h"
|
||||
#include <emscripten/bind.h>
|
||||
#include "config.h"
|
||||
#include "jpeglib.h"
|
||||
#include "cdjpeg.h"
|
||||
|
||||
// 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
|
||||
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
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
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;
|
||||
};
|
||||
|
||||
int version() {
|
||||
char buffer[] = xstr(MOZJPEG_VERSION);
|
||||
int version = 0;
|
||||
@@ -28,27 +47,17 @@ int version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
uint8_t* create_buffer(int width, int height) {
|
||||
return malloc(width * height * 4 * sizeof(uint8_t));
|
||||
int create_buffer(int width, int height) {
|
||||
return (int) malloc(width * height * 4 * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void destroy_buffer(uint8_t* p) {
|
||||
free(p);
|
||||
void destroy_buffer(int p) {
|
||||
free((uint8_t*) p);
|
||||
}
|
||||
|
||||
int result[2];
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void encode(uint8_t* image_buffer, int image_width, int image_height, int quality) {
|
||||
// Manually convert RGBA data into RGB
|
||||
for(int y = 0; y < image_height; y++) {
|
||||
for(int x = 0; x < image_width; x++) {
|
||||
image_buffer[(y*image_width + x)*3 + 0] = image_buffer[(y*image_width + x)*4 + 0];
|
||||
image_buffer[(y*image_width + x)*3 + 1] = image_buffer[(y*image_width + x)*4 + 1];
|
||||
image_buffer[(y*image_width + x)*3 + 2] = image_buffer[(y*image_width + x)*4 + 2];
|
||||
}
|
||||
}
|
||||
void encode(int image_in, int image_width, int image_height, MozJpegOptions opts) {
|
||||
uint8_t* image_buffer = (uint8_t*) image_in;
|
||||
|
||||
// The code below is basically the `write_JPEG_file` function from
|
||||
// https://github.com/mozilla/mozjpeg/blob/master/example.c
|
||||
@@ -109,18 +118,48 @@ void encode(uint8_t* image_buffer, int image_width, int image_height, int qualit
|
||||
*/
|
||||
cinfo.image_width = image_width; /* image width and height, in pixels */
|
||||
cinfo.image_height = image_height;
|
||||
cinfo.input_components = 3; /* # of color components per pixel */
|
||||
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
|
||||
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);
|
||||
|
||||
/* Now you can set any non-default parameters you wish to.
|
||||
* Here we just illustrate the use of quality (quantization table) scaling:
|
||||
*/
|
||||
jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
|
||||
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);
|
||||
|
||||
std::string quality_str = std::to_string(opts.quality);
|
||||
char const *pqual = quality_str.c_str();
|
||||
|
||||
set_quality_ratings(&cinfo, (char*) pqual, opts.baseline);
|
||||
|
||||
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.
|
||||
@@ -136,7 +175,7 @@ void encode(uint8_t* image_buffer, int image_width, int image_height, int qualit
|
||||
* To keep things simple, we pass one scanline per call; you can pass
|
||||
* more if you wish, though.
|
||||
*/
|
||||
row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
|
||||
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.
|
||||
@@ -161,18 +200,39 @@ void encode(uint8_t* image_buffer, int image_width, int image_height, int qualit
|
||||
/* And we're done! */
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
void free_result() {
|
||||
free(result[0]); // not sure if this is right with mozjpeg
|
||||
free((void*)result[0]); // not sure if this is right with mozjpeg
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int get_result_pointer() {
|
||||
return result[0];
|
||||
}
|
||||
|
||||
EMSCRIPTEN_KEEPALIVE
|
||||
int get_result_size() {
|
||||
return result[1];
|
||||
}
|
||||
|
||||
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)
|
||||
;
|
||||
|
||||
function("version", &version);
|
||||
function("create_buffer", &create_buffer, allow_raw_pointers());
|
||||
function("destroy_buffer", &destroy_buffer, allow_raw_pointers());
|
||||
function("encode", &encode, allow_raw_pointers());
|
||||
function("free_result", &free_result);
|
||||
function("get_result_pointer", &get_result_pointer, allow_raw_pointers());
|
||||
function("get_result_size", &get_result_size, allow_raw_pointers());
|
||||
}
|
||||
14
codecs/mozjpeg_enc/mozjpeg_enc.d.ts
vendored
14
codecs/mozjpeg_enc/mozjpeg_enc.d.ts
vendored
@@ -1 +1,13 @@
|
||||
export default function(opts: EmscriptenWasm.ModuleOpts): EmscriptenWasm.Module;
|
||||
import { EncodeOptions } from '../../src/codecs/mozjpeg/encoder';
|
||||
|
||||
interface MozJPEGModule extends EmscriptenWasm.Module {
|
||||
create_buffer(width: number, height: number): number;
|
||||
encode(pointer: number, width: number, height: number, options: EncodeOptions): void;
|
||||
get_result_pointer(): number;
|
||||
get_result_size(): number;
|
||||
free_result(): void;
|
||||
destroy_buffer(pointer: number): void;
|
||||
}
|
||||
|
||||
|
||||
export default function(opts: EmscriptenWasm.ModuleOpts): MozJPEGModule;
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -4,7 +4,7 @@
|
||||
"install": "napa",
|
||||
"build": "npm run build:library && npm run build:wasm",
|
||||
"build:library": "cd node_modules/mozjpeg && autoreconf -fiv && docker run --rm -v $(pwd):/src trzeci/emscripten emconfigure ./configure --without-simd && docker run --rm -v $(pwd):/src trzeci/emscripten emmake make libjpeg.la",
|
||||
"build:wasm": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc -O3 -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]' -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"mozjpeg_enc\"' -I node_modules/mozjpeg -o ./mozjpeg_enc.js mozjpeg_enc.c node_modules/mozjpeg/.libs/libjpeg.a"
|
||||
"build:wasm": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc --bind -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"mozjpeg_enc\"' -I node_modules/mozjpeg -o ./mozjpeg_enc.js -Wno-deprecated-register -Wno-writable-strings node_modules/mozjpeg/rdswitch.c -x c++ -std=c++11 mozjpeg_enc.cpp node_modules/mozjpeg/.libs/libjpeg.a"
|
||||
},
|
||||
"napa": {
|
||||
"mozjpeg": "mozilla/mozjpeg#v3.3.1"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "webp_enc",
|
||||
"scripts": {
|
||||
"install": "napa",
|
||||
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc --bind -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"webp_enc\"' -I node_modules/libwebp -o ./webp_enc.js -x c node_modules/libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c -x c++ -std=c++11 webp_enc.cpp "
|
||||
"build": "docker run --rm -v $(pwd):/src trzeci/emscripten emcc --bind -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s MODULARIZE=1 -s 'EXPORT_NAME=\"webp_enc\"' -I node_modules/libwebp -o ./webp_enc.js -x c node_modules/libwebp/src/{dec,dsp,demux,enc,mux,utils}/*.c -x c++ -std=c++11 webp_enc.cpp"
|
||||
},
|
||||
"napa": {
|
||||
"libwebp": "webmproject/libwebp#v1.0.0"
|
||||
|
||||
368
package-lock.json
generated
368
package-lock.json
generated
@@ -1243,13 +1243,15 @@
|
||||
}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "4.11.8",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz",
|
||||
"integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=",
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"co": "^4.6.0",
|
||||
"json-stable-stringify": "^1.0.1"
|
||||
"fast-deep-equal": "^1.0.0",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"ajv-keywords": {
|
||||
@@ -1426,10 +1428,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
|
||||
"integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
|
||||
"dev": true
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safer-buffer": "~2.1.0"
|
||||
}
|
||||
},
|
||||
"asn1.js": {
|
||||
"version": "4.10.1",
|
||||
@@ -1469,9 +1474,9 @@
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz",
|
||||
"integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=",
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
},
|
||||
"assign-symbols": {
|
||||
@@ -1552,15 +1557,15 @@
|
||||
}
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz",
|
||||
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
|
||||
"dev": true
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
|
||||
"integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==",
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
|
||||
"dev": true
|
||||
},
|
||||
"babel-code-frame": {
|
||||
@@ -2306,9 +2311,9 @@
|
||||
}
|
||||
},
|
||||
"babel-plugin-transform-react-remove-prop-types": {
|
||||
"version": "0.4.13",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.13.tgz",
|
||||
"integrity": "sha1-Mxz8BQmagII4MR14MZwnRg1IEYk=",
|
||||
"version": "0.4.14",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.14.tgz",
|
||||
"integrity": "sha512-fMlqvLZPX9v7k0Sl4SVzHofQOKTDXvQbpKx+glCm5Ar5L5KQZ8VxjCsYslQwP+KrYXCG6BY7hOp+O1tUVATTDA==",
|
||||
"dev": true
|
||||
},
|
||||
"babel-plugin-transform-regenerator": {
|
||||
@@ -2765,15 +2770,6 @@
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
|
||||
"dev": true
|
||||
},
|
||||
"boom": {
|
||||
"version": "2.10.1",
|
||||
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
|
||||
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hoek": "2.x.x"
|
||||
}
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
@@ -3462,12 +3458,6 @@
|
||||
"requires": {
|
||||
"for-in": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3902,15 +3892,6 @@
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"cryptiles": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz",
|
||||
"integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boom": "2.x.x"
|
||||
}
|
||||
},
|
||||
"crypto-browserify": {
|
||||
"version": "3.12.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
|
||||
@@ -4093,14 +4074,6 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
@@ -4490,13 +4463,14 @@
|
||||
}
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
|
||||
"integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"jsbn": "~0.1.0"
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"editions": {
|
||||
@@ -4530,9 +4504,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
|
||||
"integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
|
||||
"integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"bn.js": "^4.4.0",
|
||||
@@ -5287,13 +5261,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
|
||||
"integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.5",
|
||||
"combined-stream": "1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
@@ -5986,14 +5960,6 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"gh-got": {
|
||||
@@ -6305,19 +6271,19 @@
|
||||
"dev": true
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz",
|
||||
"integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
|
||||
"dev": true
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz",
|
||||
"integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=",
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^4.9.1",
|
||||
"har-schema": "^1.0.5"
|
||||
"ajv": "^5.1.0",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"has": {
|
||||
@@ -6429,18 +6395,6 @@
|
||||
"minimalistic-assert": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"hawk": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz",
|
||||
"integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boom": "2.x.x",
|
||||
"cryptiles": "2.x.x",
|
||||
"hoek": "2.x.x",
|
||||
"sntp": "1.x.x"
|
||||
}
|
||||
},
|
||||
"he": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
|
||||
@@ -6458,12 +6412,6 @@
|
||||
"minimalistic-crypto-utils": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"hoek": {
|
||||
"version": "2.16.3",
|
||||
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=",
|
||||
"dev": true
|
||||
},
|
||||
"home-or-tmp": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
|
||||
@@ -6658,12 +6606,12 @@
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
|
||||
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^0.2.0",
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
@@ -7619,15 +7567,6 @@
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A="
|
||||
},
|
||||
"json-stable-stringify": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
|
||||
"integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jsonify": "~0.0.0"
|
||||
}
|
||||
},
|
||||
"json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
@@ -7661,14 +7600,6 @@
|
||||
"extsprintf": "1.3.0",
|
||||
"json-schema": "0.2.3",
|
||||
"verror": "1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"keyv": {
|
||||
@@ -8848,8 +8779,7 @@
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
||||
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
@@ -8916,9 +8846,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node-gyp": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.7.0.tgz",
|
||||
"integrity": "sha512-qDQE/Ft9xXP6zphwx4sD0t+VhwV7yFaloMpfbL2QnnDZcyaiakWlLdtFGGQfTAwpFHdpbRhRxVhIHN1OKAjgbg==",
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
|
||||
"integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fstream": "^1.0.0",
|
||||
@@ -8928,49 +8858,13 @@
|
||||
"nopt": "2 || 3",
|
||||
"npmlog": "0 || 1 || 2 || 3 || 4",
|
||||
"osenv": "0",
|
||||
"request": ">=2.9.0 <2.82.0",
|
||||
"request": "^2.87.0",
|
||||
"rimraf": "2",
|
||||
"semver": "~5.3.0",
|
||||
"tar": "^2.0.0",
|
||||
"which": "1"
|
||||
},
|
||||
"dependencies": {
|
||||
"qs": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
|
||||
"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=",
|
||||
"dev": true
|
||||
},
|
||||
"request": {
|
||||
"version": "2.81.0",
|
||||
"resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz",
|
||||
"integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aws-sign2": "~0.6.0",
|
||||
"aws4": "^1.2.1",
|
||||
"caseless": "~0.12.0",
|
||||
"combined-stream": "~1.0.5",
|
||||
"extend": "~3.0.0",
|
||||
"forever-agent": "~0.6.1",
|
||||
"form-data": "~2.1.1",
|
||||
"har-validator": "~4.2.1",
|
||||
"hawk": "~3.1.3",
|
||||
"http-signature": "~1.1.0",
|
||||
"is-typedarray": "~1.0.0",
|
||||
"isstream": "~0.1.2",
|
||||
"json-stringify-safe": "~5.0.1",
|
||||
"mime-types": "~2.1.7",
|
||||
"oauth-sign": "~0.8.1",
|
||||
"performance-now": "^0.2.0",
|
||||
"qs": "~6.4.0",
|
||||
"safe-buffer": "^5.0.1",
|
||||
"stringstream": "~0.0.4",
|
||||
"tough-cookie": "~2.3.0",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
|
||||
@@ -9011,9 +8905,9 @@
|
||||
}
|
||||
},
|
||||
"node-sass": {
|
||||
"version": "4.9.2",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.2.tgz",
|
||||
"integrity": "sha512-LdxoJLZutx0aQXHtWIYwJKMj+9pTjneTcLWJgzf2XbGu0q5pRNqW5QvFCEdm3mc5rJOdru/mzln5d0EZLacf6g==",
|
||||
"version": "4.9.3",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.3.tgz",
|
||||
"integrity": "sha512-XzXyGjO+84wxyH7fV6IwBOTrEBe2f0a6SBze9QWWYR/cL74AcQUks2AsqcCZenl/Fp/JVbuEaLpgrLtocwBUww==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-foreach": "^0.1.3",
|
||||
@@ -9029,7 +8923,7 @@
|
||||
"meow": "^3.7.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nan": "^2.10.0",
|
||||
"node-gyp": "^3.3.1",
|
||||
"node-gyp": "^3.8.0",
|
||||
"npmlog": "^4.0.0",
|
||||
"request": "2.87.0",
|
||||
"sass-graph": "^2.2.4",
|
||||
@@ -9060,12 +8954,6 @@
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz",
|
||||
"integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
@@ -9748,9 +9636,9 @@
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz",
|
||||
"integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"dev": true
|
||||
},
|
||||
"pify": {
|
||||
@@ -10413,9 +10301,9 @@
|
||||
}
|
||||
},
|
||||
"preact": {
|
||||
"version": "8.2.9",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-8.2.9.tgz",
|
||||
"integrity": "sha512-ThuGXBmJS3VsT+jIP+eQufD3L8pRw/PY3FoCys6O9Pu6aF12Pn9zAJDX99TfwRAFOCEKm/P0lwiPTbqKMJp0fA=="
|
||||
"version": "8.3.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-8.3.1.tgz",
|
||||
"integrity": "sha512-s8H1Y8O9e+mOBo3UP1jvWqArPmjCba2lrrGLlq/0kN1XuIINUbYtf97iiXKxCuG3eYwmppPKnyW2DBrNj/TuTg=="
|
||||
},
|
||||
"preact-i18n": {
|
||||
"version": "1.2.2",
|
||||
@@ -11362,76 +11250,6 @@
|
||||
"tough-cookie": "~2.3.3",
|
||||
"tunnel-agent": "^0.6.0",
|
||||
"uuid": "^3.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"co": "^4.6.0",
|
||||
"fast-deep-equal": "^1.0.0",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
},
|
||||
"aws-sign2": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
|
||||
"dev": true
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"har-schema": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
|
||||
"dev": true
|
||||
},
|
||||
"har-validator": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
|
||||
"integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^5.1.0",
|
||||
"har-schema": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"assert-plus": "^1.0.0",
|
||||
"jsprim": "^1.2.2",
|
||||
"sshpk": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
@@ -11691,16 +11509,17 @@
|
||||
}
|
||||
},
|
||||
"sass-loader": {
|
||||
"version": "6.0.7",
|
||||
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.7.tgz",
|
||||
"integrity": "sha512-JoiyD00Yo1o61OJsoP2s2kb19L1/Y2p3QFcCdWdF6oomBGKVYuZyqHWemRBfQ2uGYsk+CH3eCguXNfpjzlcpaA==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz",
|
||||
"integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"clone-deep": "^2.0.1",
|
||||
"loader-utils": "^1.0.1",
|
||||
"lodash.tail": "^4.1.1",
|
||||
"neo-async": "^2.5.0",
|
||||
"pify": "^3.0.0"
|
||||
"pify": "^3.0.0",
|
||||
"semver": "^5.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"pify": {
|
||||
@@ -12131,15 +11950,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"sntp": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
|
||||
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"hoek": "2.x.x"
|
||||
}
|
||||
},
|
||||
"sockjs": {
|
||||
"version": "0.3.19",
|
||||
"resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz",
|
||||
@@ -12377,14 +12187,6 @@
|
||||
"jsbn": "~0.1.0",
|
||||
"safer-buffer": "^2.0.2",
|
||||
"tweetnacl": "~0.14.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ssri": {
|
||||
@@ -12537,12 +12339,6 @@
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz",
|
||||
"integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==",
|
||||
"dev": true
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
@@ -12595,9 +12391,9 @@
|
||||
}
|
||||
},
|
||||
"style-loader": {
|
||||
"version": "0.20.3",
|
||||
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.20.3.tgz",
|
||||
"integrity": "sha512-2I7AVP73MvK33U7B9TKlYZAqdROyMXDYSMvHLX43qy3GCOaJNiV6i0v/sv9idWIaQ42Yn2dNv79Q5mKXbKhAZg==",
|
||||
"version": "0.22.1",
|
||||
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.22.1.tgz",
|
||||
"integrity": "sha512-WXUrLeinPIR1Oat3PfCDro7qTniwNTJqGqv1KcQiL3JR5PzrVLTyNsd9wTsPXG/qNCJ7lzR2NY/QDjFsP7nuSQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^1.1.0",
|
||||
@@ -13157,9 +12953,9 @@
|
||||
}
|
||||
},
|
||||
"uglifyjs-webpack-plugin": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.7.tgz",
|
||||
"integrity": "sha512-1VicfKhCYHLS8m1DCApqBhoulnASsEoJ/BvpUpP4zoNAPpKzdH+ghk0olGJMmwX2/jprK2j3hAHdUbczBSy2FA==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz",
|
||||
"integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"cacache": "^10.0.4",
|
||||
@@ -13506,14 +13302,6 @@
|
||||
"assert-plus": "^1.0.0",
|
||||
"core-util-is": "1.0.2",
|
||||
"extsprintf": "^1.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"vinyl": {
|
||||
@@ -13571,9 +13359,9 @@
|
||||
}
|
||||
},
|
||||
"webpack": {
|
||||
"version": "4.16.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.16.2.tgz",
|
||||
"integrity": "sha512-Fw+RtyJD9ekQ6Mh6e/hYeoafIKK6bP6qS7EVnZ3hejt+1Ah3JCJZTGE0e5S6Eq4ijIVht6ktWOEqJfm92+5MLw==",
|
||||
"version": "4.16.5",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.16.5.tgz",
|
||||
"integrity": "sha512-i5cHYHonzSc1zBuwB5MSzW4v9cScZFbprkHK8ZgzPDCRkQXGGpYzPmJhbus5bOrZ0tXTcQp+xyImRSvKb0b+Kw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@webassemblyjs/ast": "1.5.13",
|
||||
|
||||
12
package.json
12
package.json
@@ -27,7 +27,7 @@
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-plugin-transform-react-constant-elements": "^6.23.0",
|
||||
"babel-plugin-transform-react-jsx": "^6.24.1",
|
||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.13",
|
||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.14",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-register": "^6.26.0",
|
||||
"clean-webpack-plugin": "^0.1.19",
|
||||
@@ -40,14 +40,14 @@
|
||||
"if-env": "^1.0.4",
|
||||
"loader-utils": "^1.1.0",
|
||||
"mini-css-extract-plugin": "^0.3.0",
|
||||
"node-sass": "^4.9.2",
|
||||
"node-sass": "^4.9.3",
|
||||
"optimize-css-assets-webpack-plugin": "^4.0.3",
|
||||
"progress-bar-webpack-plugin": "^1.11.0",
|
||||
"raw-loader": "^0.5.1",
|
||||
"sass-loader": "^6.0.7",
|
||||
"sass-loader": "^7.1.0",
|
||||
"script-ext-html-webpack-plugin": "^2.0.1",
|
||||
"source-map-loader": "^0.2.3",
|
||||
"style-loader": "^0.20.3",
|
||||
"style-loader": "^0.22.1",
|
||||
"ts-loader": "^4.4.2",
|
||||
"tslint": "^5.11.0",
|
||||
"tslint-config-airbnb": "^5.9.2",
|
||||
@@ -55,7 +55,7 @@
|
||||
"tslint-react": "^3.6.0",
|
||||
"typescript": "^2.9.2",
|
||||
"typings-for-css-modules-loader": "^1.7.0",
|
||||
"webpack": "^4.16.2",
|
||||
"webpack": "^4.16.5",
|
||||
"webpack-bundle-analyzer": "^2.13.1",
|
||||
"webpack-cli": "^2.1.5",
|
||||
"webpack-dev-server": "^3.1.5",
|
||||
@@ -68,7 +68,7 @@
|
||||
"comlink-loader": "^1.0.0",
|
||||
"filesize": "^3.6.1",
|
||||
"material-components-web": "^0.32.0",
|
||||
"preact": "^8.2.9",
|
||||
"preact": "^8.3.1",
|
||||
"preact-i18n": "^1.2.2",
|
||||
"preact-material-components": "^1.4.7",
|
||||
"preact-router": "^2.6.1"
|
||||
|
||||
@@ -1,22 +1,10 @@
|
||||
import mozjpeg_enc from '../../../codecs/mozjpeg_enc/mozjpeg_enc';
|
||||
import mozjpeg_enc, { MozJPEGModule } from '../../../codecs/mozjpeg_enc/mozjpeg_enc';
|
||||
// Using require() so TypeScript doesn’t complain about this not being a module.
|
||||
import { EncodeOptions } from './encoder';
|
||||
const wasmBinaryUrl = require('../../../codecs/mozjpeg_enc/mozjpeg_enc.wasm');
|
||||
|
||||
// API exposed by wasm module. Details in the codec’s README.
|
||||
interface ModuleAPI {
|
||||
version(): number;
|
||||
create_buffer(width: number, height: number): number;
|
||||
destroy_buffer(pointer: number): void;
|
||||
encode(buffer: number, width: number, height: number, quality: number): void;
|
||||
free_result(): void;
|
||||
get_result_pointer(): number;
|
||||
get_result_size(): number;
|
||||
}
|
||||
|
||||
export default class MozJpegEncoder {
|
||||
private emscriptenModule: Promise<EmscriptenWasm.Module>;
|
||||
private api: Promise<ModuleAPI>;
|
||||
private emscriptenModule: Promise<MozJPEGModule>;
|
||||
|
||||
constructor() {
|
||||
this.emscriptenModule = new Promise((resolve) => {
|
||||
@@ -41,37 +29,20 @@ export default class MozJpegEncoder {
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
this.api = (async () => {
|
||||
// Not sure why, but TypeScript complains that I am using
|
||||
// `emscriptenModule` before it’s getting assigned, which is clearly not
|
||||
// true :shrug: Using `any`
|
||||
const m = await (this as any).emscriptenModule;
|
||||
return {
|
||||
version: m.cwrap('version', 'number', []),
|
||||
create_buffer: m.cwrap('create_buffer', 'number', ['number', 'number']),
|
||||
destroy_buffer: m.cwrap('destroy_buffer', '', ['number']),
|
||||
encode: m.cwrap('encode', '', ['number', 'number', 'number', 'number']),
|
||||
free_result: m.cwrap('free_result', '', []),
|
||||
get_result_pointer: m.cwrap('get_result_pointer', 'number', []),
|
||||
get_result_size: m.cwrap('get_result_size', 'number', []),
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
async encode(data: ImageData, options: EncodeOptions): Promise<ArrayBuffer> {
|
||||
const m = await this.emscriptenModule;
|
||||
const api = await this.api;
|
||||
const module = await this.emscriptenModule;
|
||||
|
||||
const p = api.create_buffer(data.width, data.height);
|
||||
m.HEAP8.set(data.data, p);
|
||||
api.encode(p, data.width, data.height, options.quality);
|
||||
const resultPointer = api.get_result_pointer();
|
||||
const resultSize = api.get_result_size();
|
||||
const resultView = new Uint8Array(m.HEAP8.buffer, resultPointer, resultSize);
|
||||
const p = module.create_buffer(data.width, data.height);
|
||||
module.HEAP8.set(data.data, p);
|
||||
module.encode(p, data.width, data.height, options);
|
||||
const resultPointer = module.get_result_pointer();
|
||||
const resultSize = module.get_result_size();
|
||||
const resultView = new Uint8Array(module.HEAP8.buffer, resultPointer, resultSize);
|
||||
const result = new Uint8Array(resultView);
|
||||
api.free_result();
|
||||
api.destroy_buffer(p);
|
||||
module.free_result();
|
||||
module.destroy_buffer(p);
|
||||
|
||||
// wasm can’t run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
|
||||
return result.buffer as ArrayBuffer;
|
||||
|
||||
@@ -1,13 +1,46 @@
|
||||
import EncoderWorker from './Encoder.worker';
|
||||
|
||||
export interface EncodeOptions { quality: number; }
|
||||
export 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;
|
||||
}
|
||||
|
||||
export interface EncoderState { type: typeof type; options: EncodeOptions; }
|
||||
|
||||
export const type = 'mozjpeg';
|
||||
export const label = 'MozJPEG';
|
||||
export const mimeType = 'image/jpeg';
|
||||
export const extension = 'jpg';
|
||||
export const defaultOptions: EncodeOptions = { quality: 7 };
|
||||
export const defaultOptions: EncodeOptions = {
|
||||
quality: 75,
|
||||
baseline: false,
|
||||
arithmetic: false,
|
||||
progressive: true,
|
||||
optimize_coding: true,
|
||||
smoothing: 0,
|
||||
color_space: MozJpegColorSpace.YCbCr,
|
||||
quant_table: 3,
|
||||
trellis_multipass: false,
|
||||
trellis_opt_zero: false,
|
||||
trellis_opt_table: false,
|
||||
trellis_loops: 1,
|
||||
};
|
||||
|
||||
export async function encode(data: ImageData, options: EncodeOptions) {
|
||||
// We need to await this because it's been comlinked.
|
||||
|
||||
@@ -1,3 +1,161 @@
|
||||
import qualityOption from '../generic/quality-option';
|
||||
import { h, Component } from 'preact';
|
||||
import { bind, inputFieldChecked, inputFieldValueAsNumber } from '../../lib/util';
|
||||
import { EncodeOptions, MozJpegColorSpace } from './encoder';
|
||||
|
||||
export default qualityOption();
|
||||
type Props = {
|
||||
options: EncodeOptions,
|
||||
onChange(newOptions: EncodeOptions): void,
|
||||
};
|
||||
|
||||
export default class MozJPEGEncoderOptions extends Component<Props, {}> {
|
||||
@bind
|
||||
onChange(event: Event) {
|
||||
const form = (event.currentTarget as HTMLInputElement).closest('form') as HTMLFormElement;
|
||||
|
||||
const options: EncodeOptions = {
|
||||
// Copy over options the form doesn't currently care about, eg arithmetic
|
||||
...this.props.options,
|
||||
// And now stuff from the form:
|
||||
// .checked
|
||||
baseline: inputFieldChecked(form.baseline),
|
||||
progressive: inputFieldChecked(form.progressive),
|
||||
optimize_coding: inputFieldChecked(form.optimize_coding),
|
||||
trellis_multipass: inputFieldChecked(form.trellis_multipass),
|
||||
trellis_opt_zero: inputFieldChecked(form.trellis_opt_zero),
|
||||
trellis_opt_table: inputFieldChecked(form.trellis_opt_table),
|
||||
// .value
|
||||
quality: inputFieldValueAsNumber(form.quality),
|
||||
smoothing: inputFieldValueAsNumber(form.smoothing),
|
||||
color_space: inputFieldValueAsNumber(form.color_space),
|
||||
quant_table: inputFieldValueAsNumber(form.quant_table),
|
||||
trellis_loops: inputFieldValueAsNumber(form.trellis_loops),
|
||||
};
|
||||
this.props.onChange(options);
|
||||
}
|
||||
|
||||
render({ options }: Props) {
|
||||
// I'm rendering both lossy and lossless forms, as it becomes much easier when
|
||||
// gathering the data.
|
||||
return (
|
||||
<form>
|
||||
<label>
|
||||
Quality:
|
||||
<input
|
||||
name="quality"
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={'' + options.quality}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
name="baseline"
|
||||
type="checkbox"
|
||||
checked={options.baseline}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
Baseline (worse but legacy-compatible)
|
||||
</label>
|
||||
<label style={{ display: options.baseline ? 'none' : '' }}>
|
||||
<input
|
||||
name="progressive"
|
||||
type="checkbox"
|
||||
checked={options.progressive}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
Progressive multi-pass rendering
|
||||
</label>
|
||||
<label style={{ display: options.baseline ? '' : 'none' }}>
|
||||
<input
|
||||
name="optimize_coding"
|
||||
type="checkbox"
|
||||
checked={options.optimize_coding}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
Optimize Huffman table
|
||||
</label>
|
||||
<label>
|
||||
Smoothing:
|
||||
<input
|
||||
name="smoothing"
|
||||
type="range"
|
||||
min="0"
|
||||
max="100"
|
||||
value={'' + options.smoothing}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
Output color space:
|
||||
<select
|
||||
name="color_space"
|
||||
value={'' + options.color_space}
|
||||
onChange={this.onChange}
|
||||
>
|
||||
<option value={MozJpegColorSpace.GRAYSCALE}>Grayscale</option>
|
||||
<option value={MozJpegColorSpace.RGB}>RGB (sub-optimal)</option>
|
||||
<option value={MozJpegColorSpace.YCbCr}>YCbCr (optimized for color)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
Quantization table:
|
||||
<select
|
||||
name="quant_table"
|
||||
value={'' + options.quant_table}
|
||||
onChange={this.onChange}
|
||||
>
|
||||
<option value="0">JPEG Annex K</option>
|
||||
<option value="1">Flat</option>
|
||||
<option value="2">MSSIM-tuned Kodak</option>
|
||||
<option value="3">ImageMagick</option>
|
||||
<option value="4">PSNR-HVS-M-tuned Kodak</option>
|
||||
<option value="5">Klein et al</option>
|
||||
<option value="6">Watson et al</option>
|
||||
<option value="7">Ahumada et al</option>
|
||||
<option value="8">Peterson et al</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
name="trellis_multipass"
|
||||
type="checkbox"
|
||||
checked={options.trellis_multipass}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
Consider multiple scans during trellis quantization
|
||||
</label>
|
||||
<label style={{ display: options.trellis_multipass ? '' : 'none' }}>
|
||||
<input
|
||||
name="trellis_opt_zero"
|
||||
type="checkbox"
|
||||
checked={options.trellis_opt_zero}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
Optimize runs of zero blocks
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
name="trellis_opt_table"
|
||||
type="checkbox"
|
||||
checked={options.trellis_opt_table}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
Optimize after trellis quantization
|
||||
</label>
|
||||
<label>
|
||||
Trellis quantization passes:
|
||||
<input
|
||||
name="trellis_loops"
|
||||
type="range"
|
||||
min="1"
|
||||
max="50"
|
||||
value={'' + options.trellis_loops}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
</label>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,14 @@ export function inputFieldValueAsNumber(field: any): number {
|
||||
* @param field An HTMLInputElement, but the casting is done here to tidy up onChange.
|
||||
*/
|
||||
export function inputFieldCheckedAsNumber(field: any): number {
|
||||
return Number((field as HTMLInputElement).checked);
|
||||
return Number(inputFieldChecked(field));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param field An HTMLInputElement, but the casting is done here to tidy up onChange.
|
||||
*/
|
||||
export function inputFieldChecked(field: any): boolean {
|
||||
return (field as HTMLInputElement).checked;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user