Add WebP2 support

This commit is contained in:
Surma
2020-10-30 16:56:52 +00:00
committed by Ingvar Stepanyan
parent e60ffddfd7
commit 18b2bd1135
24 changed files with 726 additions and 2 deletions

47
codecs/wp2/Makefile Normal file
View File

@@ -0,0 +1,47 @@
CODEC_URL = https://chromium.googlesource.com/codecs/libwebp2/+archive/c90b5b476004c9a98731ae1c175cebab5de50fbf.tar.gz
CODEC_DIR = node_modules/wp2
CODEC_BUILD_DIR := $(CODEC_DIR)/.build
CODEC_OUT := $(CODEC_BUILD_DIR)/libwebp2.a
OUT_JS = enc/wp2_enc.js dec/wp2_dec.js
OUT_WASM = $(OUT_JS:.js=.wasm)
.PHONY: all clean
all: $(OUT_JS)
%.js: %.cpp $(CODEC_OUT)
$(CXX) \
-I $(CODEC_DIR) \
${CXXFLAGS} \
${LDFLAGS} \
--bind \
--closure 1 \
-s ALLOW_MEMORY_GROWTH=1 \
-s MODULARIZE=1 \
-s 'EXPORT_NAME="$(basename $(@F))"' \
-o $@ \
$+
$(CODEC_OUT): $(CODEC_BUILD_DIR)/Makefile
cd $(CODEC_BUILD_DIR) && \
$(MAKE)
$(CODEC_BUILD_DIR)/Makefile: $(CODEC_DIR)/CMakeLists.txt
mkdir -p $(CODEC_BUILD_DIR)
cd $(CODEC_BUILD_DIR) && \
emcmake cmake \
-DWP2_ENABLE_SIMD=0 \
-DWP2_BUILD_TESTS=0 \
-DWP2_ENABLE_TESTS=0 \
-DWP2_BUILD_EXAMPLES=0 \
-DWP2_BUILD_EXTRAS=0 \
../
$(CODEC_DIR)/CMakeLists.txt:
mkdir -p $(CODEC_DIR)
curl -sL $(CODEC_URL) | tar xz -C $(CODEC_DIR)
clean:
$(RM) $(OUT_JS) $(OUT_WASM)
$(MAKE) -C $(CODEC_BUILD_DIR) clean

17
codecs/wp2/dec/README.md Normal file
View File

@@ -0,0 +1,17 @@
# WebP2 decoder
The source for the library is not open-source _yet_. The second it is we will publicize the build steps.
## Dependencies
N/A
## Example
N/A
## API
### `RawImage decode(uint8_t* image_buffer, int image_width, int image_height)`
Decodes the given WP2 buffer into raw RGBA. `RawImage` is a class with 3 fields: `buffer`, `width`, and `height`.

View File

@@ -0,0 +1,40 @@
#include <cstdio>
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include "src/wp2/decode.h"
using namespace emscripten;
class RawImage {
public:
val buffer;
int width;
int height;
RawImage(val b, int w, int h) : buffer(b), width(w), height(h) {}
};
WP2::ArgbBuffer *buffer = new WP2::ArgbBuffer(WP2_rgbA_32);
RawImage decode(std::string image_in) {
WP2Status status;
status = WP2::Decode(image_in, buffer);
if (status != WP2_STATUS_OK) {
return RawImage(val::null(), -1, -1);
}
return RawImage(val(typed_memory_view(buffer->width * buffer->height * 4,
(uint8_t *)buffer->GetRow(0))),
buffer->width, buffer->height);
}
void free_result() { delete buffer; }
EMSCRIPTEN_BINDINGS(my_module) {
class_<RawImage>("RawImage")
.property("buffer", &RawImage::buffer)
.property("width", &RawImage::width)
.property("height", &RawImage::height);
function("decode", &decode);
function("free_result", &free_result);
}

13
codecs/wp2/dec/wp2_dec.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
interface RawImage {
buffer: Uint8Array;
width: number;
height: number;
}
interface WP2Module extends EmscriptenWasm.Module {
decode(data: BufferSource): RawImage;
free_result(): void;
}
export default function(opts: EmscriptenWasm.ModuleOpts): Promise<WP2Module>;

83
codecs/wp2/dec/wp2_dec.js Normal file
View File

@@ -0,0 +1,83 @@
var wp2_dec = (function() {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
return (
function(wp2_dec) {
wp2_dec = wp2_dec || {};
var d;d||(d=typeof wp2_dec !== 'undefined' ? wp2_dec : {});var aa,ba;d.ready=new Promise(function(a,b){aa=a;ba=b});var r={},w;for(w in d)d.hasOwnProperty(w)&&(r[w]=d[w]);var ca=!1,y=!1,da=!1,ea=!1;ca="object"===typeof window;y="function"===typeof importScripts;da="object"===typeof process&&"object"===typeof process.versions&&"string"===typeof process.versions.node;ea=!ca&&!da&&!y;var z="",ha,A,ia,ja;
if(da)z=y?require("path").dirname(z)+"/":__dirname+"/",ha=function(a,b){ia||(ia=require("fs"));ja||(ja=require("path"));a=ja.normalize(a);return ia.readFileSync(a,b?null:"utf8")},A=function(a){a=ha(a,!0);a.buffer||(a=new Uint8Array(a));a.buffer||B("Assertion failed: undefined");return a},1<process.argv.length&&process.argv[1].replace(/\\/g,"/"),process.argv.slice(2),process.on("uncaughtException",function(a){throw a;}),process.on("unhandledRejection",B),d.inspect=function(){return"[Emscripten Module object]"};
else if(ea)"undefined"!=typeof read&&(ha=function(a){return read(a)}),A=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");"object"===typeof a||B("Assertion failed: undefined");return a},"undefined"!==typeof print&&("undefined"===typeof console&&(console={}),console.log=print,console.warn=console.error="undefined"!==typeof printErr?printErr:print);else if(ca||y)y?z=self.location.href:document.currentScript&&(z=document.currentScript.src),_scriptDir&&
(z=_scriptDir),0!==z.indexOf("blob:")?z=z.substr(0,z.lastIndexOf("/")+1):z="",ha=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},y&&(A=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)});var ka=d.print||console.log.bind(console),E=d.printErr||console.warn.bind(console);for(w in r)r.hasOwnProperty(w)&&(d[w]=r[w]);r=null;var F;d.wasmBinary&&(F=d.wasmBinary);var noExitRuntime;
d.noExitRuntime&&(noExitRuntime=d.noExitRuntime);"object"!==typeof WebAssembly&&B("no native wasm support detected");var G,la=new WebAssembly.Table({initial:305,maximum:305,element:"anyfunc"}),ma=!1,na="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0;
function oa(a,b,c){var e=b+c;for(c=b;a[c]&&!(c>=e);)++c;if(16<c-b&&a.subarray&&na)return na.decode(a.subarray(b,c));for(e="";b<c;){var f=a[b++];if(f&128){var g=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|g);else{var l=a[b++]&63;f=224==(f&240)?(f&15)<<12|g<<6|l:(f&7)<<18|g<<12|l<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e}
function pa(a,b,c){var e=H;if(0<c){c=b+c-1;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var l=a.charCodeAt(++f);g=65536+((g&1023)<<10)|l&1023}if(127>=g){if(b>=c)break;e[b++]=g}else{if(2047>=g){if(b+1>=c)break;e[b++]=192|g>>6}else{if(65535>=g){if(b+2>=c)break;e[b++]=224|g>>12}else{if(b+3>=c)break;e[b++]=240|g>>18;e[b++]=128|g>>12&63}e[b++]=128|g>>6&63}e[b++]=128|g&63}}e[b]=0}}var qa="undefined"!==typeof TextDecoder?new TextDecoder("utf-16le"):void 0;
function ra(a,b){var c=a>>1;for(var e=c+b/2;!(c>=e)&&sa[c];)++c;c<<=1;if(32<c-a&&qa)return qa.decode(H.subarray(a,c));c=0;for(e="";;){var f=I[a+2*c>>1];if(0==f||c==b/2)return e;++c;e+=String.fromCharCode(f)}}function ta(a,b,c){void 0===c&&(c=2147483647);if(2>c)return 0;c-=2;var e=b;c=c<2*a.length?c/2:a.length;for(var f=0;f<c;++f)I[b>>1]=a.charCodeAt(f),b+=2;I[b>>1]=0;return b-e}function ua(a){return 2*a.length}
function va(a,b){for(var c=0,e="";!(c>=b/4);){var f=J[a+4*c>>2];if(0==f)break;++c;65536<=f?(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023)):e+=String.fromCharCode(f)}return e}function wa(a,b,c){void 0===c&&(c=2147483647);if(4>c)return 0;var e=b;c=e+c-4;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var l=a.charCodeAt(++f);g=65536+((g&1023)<<10)|l&1023}J[b>>2]=g;b+=4;if(b+4>c)break}J[b>>2]=0;return b-e}
function xa(a){for(var b=0,c=0;c<a.length;++c){var e=a.charCodeAt(c);55296<=e&&57343>=e&&++c;b+=4}return b}var K,ya,H,I,sa,J,L,za,Aa;function Ba(a){K=a;d.HEAP8=ya=new Int8Array(a);d.HEAP16=I=new Int16Array(a);d.HEAP32=J=new Int32Array(a);d.HEAPU8=H=new Uint8Array(a);d.HEAPU16=sa=new Uint16Array(a);d.HEAPU32=L=new Uint32Array(a);d.HEAPF32=za=new Float32Array(a);d.HEAPF64=Aa=new Float64Array(a)}var Ca=d.INITIAL_MEMORY||16777216;
d.wasmMemory?G=d.wasmMemory:G=new WebAssembly.Memory({initial:Ca/65536,maximum:32768});G&&(K=G.buffer);Ca=K.byteLength;Ba(K);J[33292]=5376208;function Da(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(d);else{var c=b.za;"number"===typeof c?void 0===b.ra?d.dynCall_v(c):d.dynCall_vi(c,b.ra):c(void 0===b.ra?null:b.ra)}}}var Ea=[],Fa=[],Ga=[],Ha=[];function Ia(){var a=d.preRun.shift();Ea.unshift(a)}var Ja=Math.ceil,Ka=Math.floor,M=0,La=null,N=null;d.preloadedImages={};
d.preloadedAudios={};function B(a){if(d.onAbort)d.onAbort(a);E(a);ma=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");ba(a);throw a;}function Ma(a){var b=O;return String.prototype.startsWith?b.startsWith(a):0===b.indexOf(a)}function Na(){return Ma("data:application/octet-stream;base64,")}var O="wp2_dec.wasm";if(!Na()){var Oa=O;O=d.locateFile?d.locateFile(Oa,z):z+Oa}
function Pa(){try{if(F)return new Uint8Array(F);if(A)return A(O);throw"both async and sync fetching of the wasm failed";}catch(a){B(a)}}function Qa(){return F||!ca&&!y||"function"!==typeof fetch||Ma("file://")?new Promise(function(a){a(Pa())}):fetch(O,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+O+"'";return a.arrayBuffer()}).catch(function(){return Pa()})}Fa.push({za:function(){Ra()}});function Sa(){return 0<Sa.ma}
function Ta(a){switch(a){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+a);}}var Ua=void 0;function P(a){for(var b="";H[a];)b+=Ua[H[a++]];return b}var Q={},R={},Va={};function Wa(a){if(void 0===a)return"_unknown";a=a.replace(/[^a-zA-Z0-9_]/g,"$");var b=a.charCodeAt(0);return 48<=b&&57>=b?"_"+a:a}
function Xa(a,b){a=Wa(a);return(new Function("body","return function "+a+'() {\n "use strict"; return body.apply(this, arguments);\n};\n'))(b)}function Ya(a){var b=Error,c=Xa(a,function(e){this.name=a;this.message=e;e=Error(e).stack;void 0!==e&&(this.stack=this.toString()+"\n"+e.replace(/^Error(:[^\n]*)?\n/,""))});c.prototype=Object.create(b.prototype);c.prototype.constructor=c;c.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message};return c}
var Za=void 0;function S(a){throw new Za(a);}var $a=void 0;function ab(a){throw new $a(a);}function bb(a,b,c){function e(k){k=c(k);k.length!==a.length&&ab("Mismatched type converter count");for(var h=0;h<a.length;++h)T(a[h],k[h])}a.forEach(function(k){Va[k]=b});var f=Array(b.length),g=[],l=0;b.forEach(function(k,h){R.hasOwnProperty(k)?f[h]=R[k]:(g.push(k),Q.hasOwnProperty(k)||(Q[k]=[]),Q[k].push(function(){f[h]=R[k];++l;l===g.length&&e(f)}))});0===g.length&&e(f)}
function T(a,b,c){c=c||{};if(!("argPackAdvance"in b))throw new TypeError("registerType registeredInstance requires argPackAdvance");var e=b.name;a||S('type "'+e+'" must have a positive integer typeid pointer');if(R.hasOwnProperty(a)){if(c.Ca)return;S("Cannot register type '"+e+"' twice")}R[a]=b;delete Va[a];Q.hasOwnProperty(a)&&(b=Q[a],delete Q[a],b.forEach(function(f){f()}))}function cb(a){return{count:a.count,la:a.la,na:a.na,aa:a.aa,da:a.da,ea:a.ea,fa:a.fa}}
function db(a){S(a.$.da.ba.name+" instance already deleted")}var eb=!1;function fb(){}function gb(a){--a.count.value;0===a.count.value&&(a.ea?a.fa.ka(a.ea):a.da.ba.ka(a.aa))}
function hb(a){if("undefined"===typeof FinalizationGroup)return hb=function(b){return b},a;eb=new FinalizationGroup(function(b){for(var c=b.next();!c.done;c=b.next())c=c.value,c.aa?gb(c):console.warn("object already deleted: "+c.aa)});hb=function(b){eb.register(b,b.$,b.$);return b};fb=function(b){eb.unregister(b.$)};return hb(a)}var ib=void 0,jb=[];function kb(){for(;jb.length;){var a=jb.pop();a.$.la=!1;a["delete"]()}}function U(){}var lb={};
function mb(a,b){var c=d;if(void 0===c[a].ha){var e=c[a];c[a]=function(){c[a].ha.hasOwnProperty(arguments.length)||S("Function '"+b+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+c[a].ha+")!");return c[a].ha[arguments.length].apply(this,arguments)};c[a].ha=[];c[a].ha[e.wa]=e}}
function nb(a,b,c){d.hasOwnProperty(a)?((void 0===c||void 0!==d[a].ha&&void 0!==d[a].ha[c])&&S("Cannot register public name '"+a+"' twice"),mb(a,a),d.hasOwnProperty(c)&&S("Cannot register multiple overloads of a function with the same number of arguments ("+c+")!"),d[a].ha[c]=b):(d[a]=b,void 0!==c&&(d[a].Ia=c))}function ob(a,b,c,e,f,g,l,k){this.name=a;this.constructor=b;this.ja=c;this.ka=e;this.ga=f;this.Aa=g;this.oa=l;this.ya=k}
function pb(a,b,c){for(;b!==c;)b.oa||S("Expected null or instance of "+c.name+", got an instance of "+b.name),a=b.oa(a),b=b.ga;return a}function qb(a,b){if(null===b)return this.sa&&S("null is not a valid "+this.name),0;b.$||S('Cannot pass "'+V(b)+'" as a '+this.name);b.$.aa||S("Cannot pass deleted object as a pointer of type "+this.name);return pb(b.$.aa,b.$.da.ba,this.ba)}
function rb(a,b){if(null===b){this.sa&&S("null is not a valid "+this.name);if(this.qa){var c=this.Ea();null!==a&&a.push(this.ka,c);return c}return 0}b.$||S('Cannot pass "'+V(b)+'" as a '+this.name);b.$.aa||S("Cannot pass deleted object as a pointer of type "+this.name);!this.pa&&b.$.da.pa&&S("Cannot convert argument of type "+(b.$.fa?b.$.fa.name:b.$.da.name)+" to parameter type "+this.name);c=pb(b.$.aa,b.$.da.ba,this.ba);if(this.qa)switch(void 0===b.$.ea&&S("Passing raw pointer to smart pointer is illegal"),
this.Ga){case 0:b.$.fa===this?c=b.$.ea:S("Cannot convert argument of type "+(b.$.fa?b.$.fa.name:b.$.da.name)+" to parameter type "+this.name);break;case 1:c=b.$.ea;break;case 2:if(b.$.fa===this)c=b.$.ea;else{var e=b.clone();c=this.Fa(c,sb(function(){e["delete"]()}));null!==a&&a.push(this.ka,c)}break;default:S("Unsupporting sharing policy")}return c}
function tb(a,b){if(null===b)return this.sa&&S("null is not a valid "+this.name),0;b.$||S('Cannot pass "'+V(b)+'" as a '+this.name);b.$.aa||S("Cannot pass deleted object as a pointer of type "+this.name);b.$.da.pa&&S("Cannot convert argument of type "+b.$.da.name+" to parameter type "+this.name);return pb(b.$.aa,b.$.da.ba,this.ba)}function vb(a){return this.fromWireType(L[a>>2])}function wb(a,b,c){if(b===c)return a;if(void 0===c.ga)return null;a=wb(a,b,c.ga);return null===a?null:c.ya(a)}var xb={};
function yb(a,b){for(void 0===b&&S("ptr should not be undefined");a.ga;)b=a.oa(b),a=a.ga;return xb[b]}function zb(a,b){b.da&&b.aa||ab("makeClassHandle requires ptr and ptrType");!!b.fa!==!!b.ea&&ab("Both smartPtrType and smartPtr must be specified");b.count={value:1};return hb(Object.create(a,{$:{value:b}}))}
function W(a,b,c,e){this.name=a;this.ba=b;this.sa=c;this.pa=e;this.qa=!1;this.ka=this.Fa=this.Ea=this.va=this.Ga=this.Da=void 0;void 0!==b.ga?this.toWireType=rb:(this.toWireType=e?qb:tb,this.ia=null)}function Ab(a,b,c){d.hasOwnProperty(a)||ab("Replacing nonexistant public symbol");void 0!==d[a].ha&&void 0!==c?d[a].ha[c]=b:(d[a]=b,d[a].wa=c)}
function X(a,b){a=P(a);var c=d["dynCall_"+a];for(var e=[],f=1;f<a.length;++f)e.push("a"+f);f="return function dynCall_"+(a+"_"+b)+"("+e.join(", ")+") {\n";f+=" return dynCall(rawFunction"+(e.length?", ":"")+e.join(", ")+");\n";c=(new Function("dynCall","rawFunction",f+"};\n"))(c,b);"function"!==typeof c&&S("unknown function pointer with signature "+a+": "+b);return c}var Bb=void 0;function Cb(a){a=Db(a);var b=P(a);Y(a);return b}
function Eb(a,b){function c(g){f[g]||R[g]||(Va[g]?Va[g].forEach(c):(e.push(g),f[g]=!0))}var e=[],f={};b.forEach(c);throw new Bb(a+": "+e.map(Cb).join([", "]));}function Fb(a){for(;a.length;){var b=a.pop();a.pop()(b)}}function Gb(a,b,c){a instanceof Object||S(c+' with invalid "this": '+a);a instanceof b.ba.constructor||S(c+' incompatible with "this" of type '+a.constructor.name);a.$.aa||S("cannot call emscripten binding method "+c+" on deleted object");return pb(a.$.aa,a.$.da.ba,b.ba)}
var Hb=[],Z=[{},{value:void 0},{value:null},{value:!0},{value:!1}];function Ib(a){4<a&&0===--Z[a].ta&&(Z[a]=void 0,Hb.push(a))}function sb(a){switch(a){case void 0:return 1;case null:return 2;case !0:return 3;case !1:return 4;default:var b=Hb.length?Hb.pop():Z.length;Z[b]={ta:1,value:a};return b}}function V(a){if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a}
function Jb(a,b){switch(b){case 2:return function(c){return this.fromWireType(za[c>>2])};case 3:return function(c){return this.fromWireType(Aa[c>>3])};default:throw new TypeError("Unknown float type: "+a);}}function Kb(a){var b=Function;if(!(b instanceof Function))throw new TypeError("new_ called with constructor type "+typeof b+" which is not a function");var c=Xa(b.name||"unknownFunctionName",function(){});c.prototype=b.prototype;c=new c;a=b.apply(c,a);return a instanceof Object?a:c}
function Lb(a,b){for(var c=[],e=0;e<a;e++)c.push(J[(b>>2)+e]);return c}function Mb(a,b,c){switch(b){case 0:return c?function(e){return ya[e]}:function(e){return H[e]};case 1:return c?function(e){return I[e>>1]}:function(e){return sa[e>>1]};case 2:return c?function(e){return J[e>>2]}:function(e){return L[e>>2]};default:throw new TypeError("Unknown integer type: "+a);}}for(var Nb=[null,[],[]],Ob=Array(256),Pb=0;256>Pb;++Pb)Ob[Pb]=String.fromCharCode(Pb);Ua=Ob;Za=d.BindingError=Ya("BindingError");
$a=d.InternalError=Ya("InternalError");U.prototype.isAliasOf=function(a){if(!(this instanceof U&&a instanceof U))return!1;var b=this.$.da.ba,c=this.$.aa,e=a.$.da.ba;for(a=a.$.aa;b.ga;)c=b.oa(c),b=b.ga;for(;e.ga;)a=e.oa(a),e=e.ga;return b===e&&c===a};U.prototype.clone=function(){this.$.aa||db(this);if(this.$.na)return this.$.count.value+=1,this;var a=hb(Object.create(Object.getPrototypeOf(this),{$:{value:cb(this.$)}}));a.$.count.value+=1;a.$.la=!1;return a};
U.prototype["delete"]=function(){this.$.aa||db(this);this.$.la&&!this.$.na&&S("Object already scheduled for deletion");fb(this);gb(this.$);this.$.na||(this.$.ea=void 0,this.$.aa=void 0)};U.prototype.isDeleted=function(){return!this.$.aa};U.prototype.deleteLater=function(){this.$.aa||db(this);this.$.la&&!this.$.na&&S("Object already scheduled for deletion");jb.push(this);1===jb.length&&ib&&ib(kb);this.$.la=!0;return this};W.prototype.Ba=function(a){this.va&&(a=this.va(a));return a};
W.prototype.ua=function(a){this.ka&&this.ka(a)};W.prototype.argPackAdvance=8;W.prototype.readValueFromPointer=vb;W.prototype.deleteObject=function(a){if(null!==a)a["delete"]()};
W.prototype.fromWireType=function(a){function b(){return this.qa?zb(this.ba.ja,{da:this.Da,aa:c,fa:this,ea:a}):zb(this.ba.ja,{da:this,aa:a})}var c=this.Ba(a);if(!c)return this.ua(a),null;var e=yb(this.ba,c);if(void 0!==e){if(0===e.$.count.value)return e.$.aa=c,e.$.ea=a,e.clone();e=e.clone();this.ua(a);return e}e=this.ba.Aa(c);e=lb[e];if(!e)return b.call(this);e=this.pa?e.xa:e.pointerType;var f=wb(c,this.ba,e.ba);return null===f?b.call(this):this.qa?zb(e.ba.ja,{da:e,aa:f,fa:this,ea:a}):zb(e.ba.ja,
{da:e,aa:f})};d.getInheritedInstanceCount=function(){return Object.keys(xb).length};d.getLiveInheritedInstances=function(){var a=[],b;for(b in xb)xb.hasOwnProperty(b)&&a.push(xb[b]);return a};d.flushPendingDeletes=kb;d.setDelayFunction=function(a){ib=a;jb.length&&ib&&ib(kb)};Bb=d.UnboundTypeError=Ya("UnboundTypeError");d.count_emval_handles=function(){for(var a=0,b=5;b<Z.length;++b)void 0!==Z[b]&&++a;return a};d.get_first_emval=function(){for(var a=5;a<Z.length;++a)if(void 0!==Z[a])return Z[a];return null};
var Rb={s:function(a){return Qb(a)},r:function(a){"uncaught_exception"in Sa?Sa.ma++:Sa.ma=1;throw a;},x:function(a,b,c,e,f){var g=Ta(c);b=P(b);T(a,{name:b,fromWireType:function(l){return!!l},toWireType:function(l,k){return k?e:f},argPackAdvance:8,readValueFromPointer:function(l){if(1===c)var k=ya;else if(2===c)k=I;else if(4===c)k=J;else throw new TypeError("Unknown boolean type size: "+b);return this.fromWireType(k[l>>g])},ia:null})},t:function(a,b,c,e,f,g,l,k,h,p,m,q,t){m=P(m);g=X(f,g);k&&(k=X(l,
k));p&&(p=X(h,p));t=X(q,t);var u=Wa(m);nb(u,function(){Eb("Cannot construct "+m+" due to unbound types",[e])});bb([a,b,c],e?[e]:[],function(n){n=n[0];if(e){var D=n.ba;var v=D.ja}else v=U.prototype;n=Xa(u,function(){if(Object.getPrototypeOf(this)!==x)throw new Za("Use 'new' to construct "+m);if(void 0===C.ma)throw new Za(m+" has no accessible constructor");var ub=C.ma[arguments.length];if(void 0===ub)throw new Za("Tried to invoke ctor of "+m+" with invalid number of parameters ("+arguments.length+
") - expected ("+Object.keys(C.ma).toString()+") parameters instead!");return ub.apply(this,arguments)});var x=Object.create(v,{constructor:{value:n}});n.prototype=x;var C=new ob(m,n,x,t,D,g,k,p);D=new W(m,C,!0,!1);v=new W(m+"*",C,!1,!1);var fa=new W(m+" const*",C,!1,!0);lb[a]={pointerType:v,xa:fa};Ab(u,n);return[D,v,fa]})},e:function(a,b,c,e,f,g,l,k,h,p){b=P(b);f=X(e,f);bb([],[a],function(m){m=m[0];var q=m.name+"."+b,t={get:function(){Eb("Cannot access "+q+" due to unbound types",[c,l])},enumerable:!0,
configurable:!0};h?t.set=function(){Eb("Cannot access "+q+" due to unbound types",[c,l])}:t.set=function(){S(q+" is a read-only property")};Object.defineProperty(m.ba.ja,b,t);bb([],h?[c,l]:[c],function(u){var n=u[0],D={get:function(){var x=Gb(this,m,q+" getter");return n.fromWireType(f(g,x))},enumerable:!0};if(h){h=X(k,h);var v=u[1];D.set=function(x){var C=Gb(this,m,q+" setter"),fa=[];h(p,C,v.toWireType(fa,x));Fb(fa)}}Object.defineProperty(m.ba.ja,b,D);return[]});return[]})},w:function(a,b){b=P(b);
T(a,{name:b,fromWireType:function(c){var e=Z[c].value;Ib(c);return e},toWireType:function(c,e){return sb(e)},argPackAdvance:8,readValueFromPointer:vb,ia:null})},l:function(a,b,c){c=Ta(c);b=P(b);T(a,{name:b,fromWireType:function(e){return e},toWireType:function(e,f){if("number"!==typeof f&&"boolean"!==typeof f)throw new TypeError('Cannot convert "'+V(f)+'" to '+this.name);return f},argPackAdvance:8,readValueFromPointer:Jb(b,c),ia:null})},g:function(a,b,c,e,f,g){var l=Lb(b,c);a=P(a);f=X(e,f);nb(a,function(){Eb("Cannot call "+
a+" due to unbound types",l)},b-1);bb([],l,function(k){var h=[k[0],null].concat(k.slice(1)),p=k=a,m=f,q=h.length;2>q&&S("argTypes array size mismatch! Must at least get return value and 'this' types!");for(var t=null!==h[1]&&!1,u=!1,n=1;n<h.length;++n)if(null!==h[n]&&void 0===h[n].ia){u=!0;break}var D="void"!==h[0].name,v="",x="";for(n=0;n<q-2;++n)v+=(0!==n?", ":"")+"arg"+n,x+=(0!==n?", ":"")+"arg"+n+"Wired";p="return function "+Wa(p)+"("+v+") {\nif (arguments.length !== "+(q-2)+") {\nthrowBindingError('function "+
p+" called with ' + arguments.length + ' arguments, expected "+(q-2)+" args!');\n}\n";u&&(p+="var destructors = [];\n");var C=u?"destructors":"null";v="throwBindingError invoker fn runDestructors retType classParam".split(" ");m=[S,m,g,Fb,h[0],h[1]];t&&(p+="var thisWired = classParam.toWireType("+C+", this);\n");for(n=0;n<q-2;++n)p+="var arg"+n+"Wired = argType"+n+".toWireType("+C+", arg"+n+"); // "+h[n+2].name+"\n",v.push("argType"+n),m.push(h[n+2]);t&&(x="thisWired"+(0<x.length?", ":"")+x);p+=(D?
"var rv = ":"")+"invoker(fn"+(0<x.length?", ":"")+x+");\n";if(u)p+="runDestructors(destructors);\n";else for(n=t?1:2;n<h.length;++n)q=1===n?"thisWired":"arg"+(n-2)+"Wired",null!==h[n].ia&&(p+=q+"_dtor("+q+"); // "+h[n].name+"\n",v.push(q+"_dtor"),m.push(h[n].ia));D&&(p+="var ret = retType.fromWireType(rv);\nreturn ret;\n");v.push(p+"}\n");h=Kb(v).apply(null,m);Ab(k,h,b-1);return[]})},b:function(a,b,c,e,f){function g(p){return p}b=P(b);-1===f&&(f=4294967295);var l=Ta(c);if(0===e){var k=32-8*c;g=function(p){return p<<
k>>>k}}var h=-1!=b.indexOf("unsigned");T(a,{name:b,fromWireType:g,toWireType:function(p,m){if("number"!==typeof m&&"boolean"!==typeof m)throw new TypeError('Cannot convert "'+V(m)+'" to '+this.name);if(m<e||m>f)throw new TypeError('Passing a number "'+V(m)+'" from JS side to C/C++ side to an argument of type "'+b+'", which is outside the valid range ['+e+", "+f+"]!");return h?m>>>0:m|0},argPackAdvance:8,readValueFromPointer:Mb(b,l,0!==e),ia:null})},a:function(a,b,c){function e(g){g>>=2;var l=L;return new f(K,
l[g+1],l[g])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array][b];c=P(c);T(a,{name:c,fromWireType:e,argPackAdvance:8,readValueFromPointer:e},{Ca:!0})},m:function(a,b){b=P(b);var c="std::string"===b;T(a,{name:b,fromWireType:function(e){var f=L[e>>2];if(c)for(var g=e+4,l=0;l<=f;++l){var k=e+4+l;if(l==f||0==H[k]){g=g?oa(H,g,k-g):"";if(void 0===h)var h=g;else h+=String.fromCharCode(0),h+=g;g=k+1}}else{h=Array(f);for(l=0;l<f;++l)h[l]=String.fromCharCode(H[e+
4+l]);h=h.join("")}Y(e);return h},toWireType:function(e,f){f instanceof ArrayBuffer&&(f=new Uint8Array(f));var g="string"===typeof f;g||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array||S("Cannot pass non-string to std::string");var l=(c&&g?function(){for(var p=0,m=0;m<f.length;++m){var q=f.charCodeAt(m);55296<=q&&57343>=q&&(q=65536+((q&1023)<<10)|f.charCodeAt(++m)&1023);127>=q?++p:p=2047>=q?p+2:65535>=q?p+3:p+4}return p}:function(){return f.length})(),k=Qb(4+l+1);L[k>>
2]=l;if(c&&g)pa(f,k+4,l+1);else if(g)for(g=0;g<l;++g){var h=f.charCodeAt(g);255<h&&(Y(k),S("String has UTF-16 code units that do not fit in 8 bits"));H[k+4+g]=h}else for(g=0;g<l;++g)H[k+4+g]=f[g];null!==e&&e.push(Y,k);return k},argPackAdvance:8,readValueFromPointer:vb,ia:function(e){Y(e)}})},f:function(a,b,c){c=P(c);if(2===b){var e=ra;var f=ta;var g=ua;var l=function(){return sa};var k=1}else 4===b&&(e=va,f=wa,g=xa,l=function(){return L},k=2);T(a,{name:c,fromWireType:function(h){for(var p=L[h>>2],
m=l(),q,t=h+4,u=0;u<=p;++u){var n=h+4+u*b;if(u==p||0==m[n>>k])t=e(t,n-t),void 0===q?q=t:(q+=String.fromCharCode(0),q+=t),t=n+b}Y(h);return q},toWireType:function(h,p){"string"!==typeof p&&S("Cannot pass non-string to C++ string type "+c);var m=g(p),q=Qb(4+m+b);L[q>>2]=m>>k;f(p,q+4,m+b);null!==h&&h.push(Y,q);return q},argPackAdvance:8,readValueFromPointer:vb,ia:function(h){Y(h)}})},y:function(a,b){b=P(b);T(a,{Ha:!0,name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},k:Ib,B:function(a){4<
a&&(Z[a].ta+=1)},o:function(a,b){var c=R[a];void 0===c&&S("_emval_take_value has unknown type "+Cb(a));a=c.readValueFromPointer(b);return sb(a)},i:function(){B()},v:function(a,b,c){H.copyWithin(a,b,b+c)},c:function(a){a>>>=0;var b=H.length;if(2147483648<a)return!1;for(var c=1;4>=c;c*=2){var e=b*(1+.2/c);e=Math.min(e,a+100663296);e=Math.max(16777216,a,e);0<e%65536&&(e+=65536-e%65536);a:{try{G.grow(Math.min(2147483648,e)-K.byteLength+65535>>>16);Ba(G.buffer);var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},
j:function(a,b,c,e){for(var f=0,g=0;g<c;g++){for(var l=J[b+8*g>>2],k=J[b+(8*g+4)>>2],h=0;h<k;h++){var p=H[l+h],m=Nb[a];0===p||10===p?((1===a?ka:E)(oa(m,0)),m.length=0):m.push(p)}f+=k}J[e>>2]=f;return 0},memory:G,n:function(){return 0},q:function(){return 0},p:function(){},A:function(){return 6},z:function(){},h:function(a){a=+a;return 0<=a?+Ka(a+.5):+Ja(a-.5)},d:function(a){a=+a;return 0<=a?+Ka(a+.5):+Ja(a-.5)},u:function(){},table:la};
(function(){function a(f){d.asm=f.exports;M--;d.monitorRunDependencies&&d.monitorRunDependencies(M);0==M&&(null!==La&&(clearInterval(La),La=null),N&&(f=N,N=null,f()))}function b(f){a(f.instance)}function c(f){return Qa().then(function(g){return WebAssembly.instantiate(g,e)}).then(f,function(g){E("failed to asynchronously prepare wasm: "+g);B(g)})}var e={a:Rb};M++;d.monitorRunDependencies&&d.monitorRunDependencies(M);if(d.instantiateWasm)try{return d.instantiateWasm(e,a)}catch(f){return E("Module.instantiateWasm callback failed with error: "+
f),!1}(function(){if(F||"function"!==typeof WebAssembly.instantiateStreaming||Na()||Ma("file://")||"function"!==typeof fetch)return c(b);fetch(O,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(b,function(g){E("wasm streaming compile failed: "+g);E("falling back to ArrayBuffer instantiation");return c(b)})})})();return{}})();
var Ra=d.___wasm_call_ctors=function(){return(Ra=d.___wasm_call_ctors=d.asm.C).apply(null,arguments)},Qb=d._malloc=function(){return(Qb=d._malloc=d.asm.D).apply(null,arguments)},Y=d._free=function(){return(Y=d._free=d.asm.E).apply(null,arguments)},Db=d.___getTypeName=function(){return(Db=d.___getTypeName=d.asm.F).apply(null,arguments)};d.___embind_register_native_and_builtin_types=function(){return(d.___embind_register_native_and_builtin_types=d.asm.G).apply(null,arguments)};
d.dynCall_ii=function(){return(d.dynCall_ii=d.asm.H).apply(null,arguments)};d.dynCall_vi=function(){return(d.dynCall_vi=d.asm.I).apply(null,arguments)};d.dynCall_iii=function(){return(d.dynCall_iii=d.asm.J).apply(null,arguments)};d.dynCall_viii=function(){return(d.dynCall_viii=d.asm.K).apply(null,arguments)};d.dynCall_vii=function(){return(d.dynCall_vii=d.asm.L).apply(null,arguments)};d.dynCall_v=function(){return(d.dynCall_v=d.asm.M).apply(null,arguments)};
d.dynCall_viiiiiii=function(){return(d.dynCall_viiiiiii=d.asm.N).apply(null,arguments)};d.dynCall_viiiiiiiii=function(){return(d.dynCall_viiiiiiiii=d.asm.O).apply(null,arguments)};d.dynCall_viiiiiiii=function(){return(d.dynCall_viiiiiiii=d.asm.P).apply(null,arguments)};d.dynCall_viiii=function(){return(d.dynCall_viiii=d.asm.Q).apply(null,arguments)};d.dynCall_viiiiii=function(){return(d.dynCall_viiiiii=d.asm.R).apply(null,arguments)};
d.dynCall_iidiiii=function(){return(d.dynCall_iidiiii=d.asm.S).apply(null,arguments)};d.dynCall_iiiii=function(){return(d.dynCall_iiiii=d.asm.T).apply(null,arguments)};d.dynCall_iiiiii=function(){return(d.dynCall_iiiiii=d.asm.U).apply(null,arguments)};d.dynCall_fi=function(){return(d.dynCall_fi=d.asm.V).apply(null,arguments)};d.dynCall_fii=function(){return(d.dynCall_fii=d.asm.W).apply(null,arguments)};d.dynCall_viiiii=function(){return(d.dynCall_viiiii=d.asm.X).apply(null,arguments)};
d.dynCall_iiii=function(){return(d.dynCall_iiii=d.asm.Y).apply(null,arguments)};d.dynCall_jiji=function(){return(d.dynCall_jiji=d.asm.Z).apply(null,arguments)};var Sb;N=function Tb(){Sb||Ub();Sb||(N=Tb)};
function Ub(){function a(){if(!Sb&&(Sb=!0,d.calledRun=!0,!ma)){Da(Fa);Da(Ga);aa(d);if(d.onRuntimeInitialized)d.onRuntimeInitialized();if(d.postRun)for("function"==typeof d.postRun&&(d.postRun=[d.postRun]);d.postRun.length;){var b=d.postRun.shift();Ha.unshift(b)}Da(Ha)}}if(!(0<M)){if(d.preRun)for("function"==typeof d.preRun&&(d.preRun=[d.preRun]);d.preRun.length;)Ia();Da(Ea);0<M||(d.setStatus?(d.setStatus("Running..."),setTimeout(function(){setTimeout(function(){d.setStatus("")},1);a()},1)):a())}}
d.run=Ub;if(d.preInit)for("function"==typeof d.preInit&&(d.preInit=[d.preInit]);0<d.preInit.length;)d.preInit.pop()();noExitRuntime=!0;Ub();
return wp2_dec.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = wp2_dec;
else if (typeof define === 'function' && define['amd'])
define([], function() { return wp2_dec; });
else if (typeof exports === 'object')
exports["wp2_dec"] = wp2_dec;

BIN
codecs/wp2/dec/wp2_dec.wasm Normal file

Binary file not shown.

17
codecs/wp2/enc/README.md Normal file
View File

@@ -0,0 +1,17 @@
# WebP2 encoder
The source for the library is not open-source _yet_. The second it is we will publicize the build steps.
## Dependencies
N/A
## Example
N/A
## API
### `UInt8Array encode(uint8_t* image_buffer, int image_width, int image_height)`
Encodes the given image with given dimension to WP2.

205
codecs/wp2/enc/wp2_enc.cpp Normal file
View File

@@ -0,0 +1,205 @@
#include <cstdio>
#include <emscripten/bind.h>
#include <emscripten/val.h>
#include "src/wp2/encode.h"
using namespace emscripten;
// enum PartitionMethod {
// // For each block size starting from biggest, take all blocks matching
// some: THRESH_VARIANCE_PARTITIONING, // uniform variance score
// // For each block size starting from biggest, find the best pos depending
// on: BIG_BLOCK_VARIANCE_RNG_PARTITIONING, // uniform variance score
// BIG_BLOCK_VARIANCE_MAX_PARTITIONING, // low variance score
// BIG_BLOCK_TRANS_AMPL_PARTITIONING, // DCT coeffs amplitude
// BIG_BLOCK_TRANS_ZEROS_PARTITIONING, // number of near zeros in DCT coeffs
// BIG_BLOCK_LUMA_RNG_PARTITIONING, // luma range score
// BIG_BLOCK_RECONS_PARTITIONING, // reconstruction score
// BIG_BLOCK_PRED_PARTITIONING, // prediction score
// BIG_BLOCK_QUANT_PARTITIONING, // pred+recons+quant score
// // For each pos starting from top left, take the best block size depending
// on: TOP_LEFT_RECONS_PARTITIONING, // reconstruction score
// TOP_LEFT_PRED_PARTITIONING, // prediction score
// TOP_LEFT_BLOCK_ENCODE_PARTITIONING, // block encoding score
// TOP_LEFT_TILE_ENCODE_PARTITIONING, // tile encoding score (slow)
// TOP_LEFT_TILE_ENCODE_DECODE_PARTITIONING, // tile enc+dec score (slow)
// // Combine several metrics in successive block size passes:
// MULTIPASS_PARTITIONING,
// // For each possible block layout, take the best one (extremely slow):
// EXHAUSTIVE_PARTITIONING, // based on tile enc+dec score
// // Split variants of methods above:
// SPLIT_BIG_BLOCK_VARIANCE_MAX_PARTITIONING,
// SPLIT_BIG_BLOCK_PRED_PARTITIONING,
// SPLIT_BIG_BLOCK_QUANT_PARTITIONING,
// SPLIT_TOP_LEFT_BLOCK_ENCODE_PARTITIONING,
// // Fixed block size (except on edges). Also depends on the partition set.
// ALL_4X4_PARTITIONING,
// ALL_8X8_PARTITIONING,
// ALL_16X16_PARTITIONING,
// ALL_32X32_PARTITIONING,
// NUM_PARTITION_METHODS
// };
// enum PartitionSet { // The smallest block size is 4x4.
// SMALL_SQUARES, // Up to 8x8
// SMALL_RECTS, // Up to 16x16
// ALL_RECTS, // Up to 32x32, ratio at most 4:1
// THICK_RECTS, // Up to 32x32, ratio at most 2:1
// MEDIUM_SQUARES, // Up to 16x16
// ALL_SQUARES, // Up to 32x32
// SOME_RECTS, // Up to 32x32, subset of frequently used rects
// NUM_PARTITION_SETS
// };
// enum class PredictorSet {
// CUSTOM_PREDICTORS = 0, // this predictor should stay first
// DC_PREDICTORS,
// ANGLE_PREDICTORS,
// VP8_PREDICTORS,
// SMOOTH_PREDICTORS,
// PAETH_PREDICTOR,
// AV1_FILTER,
// FUSE_PREDICTORS,
// ALL, // includes all of the above starting at 1
// LARGE_PREDICTORS, // fixed set for some Y blocks
// UV_PREDICTORS, // fixed set for U/V
// ALPHA_PREDICTORS, // fixed set for alpha
// LAST_PREDICTORS, // end-of-list marker
// };
// enum class Csp { kYCoCg, kYCbCr, kCustom, kYIQ };
// typedef enum {
// UVModeAdapt = 0,
// UVMode420,
// UVModeSharp,
// UVMode444,
// NumUVMode // End-of-list marker
// } UVMode;
struct WP2Options {
float quality = 75.0f; // Range: [0 = smallest file .. 100 = lossless]
// Quality in [95-100) range will use near-lossless.
// Quality 100 is strictly lossless.
// int target_size = 0; // If non-zero, set the desired target size in
// bytes. Takes precedence over the 'quality' parameter.
// float target_psnr = 0.f; // If non-zero, specifies the minimal distortion
// to try to achieve. Precedence over 'target_size'.
float alpha_quality = 100.f; // Range: [0 = smallest size .. 100 = lossless]
int speed = 5; // Quality/speed trade-off. Range: [0=fast .. 9=slower-better]
// Side parameters:
// Set whether the image will be rotated during decoding.
// Orientation decoding_orientation = Orientation::kOriginal;
// Add a heavily compressed preview to be decoded and displayed before final
// pixels (small size overhead up to kMaxPreviewSize).
// bool create_preview = false;
// TransferFunction transfer_function = WP2_TF_ITU_R_BT2020_10BIT;
// Parameters related to lossy compression only:
int pass = 1; // Number of entropy-analysis passes. Range: [1..10]
// Spatial noise shaping strength in [0(=off), 100]
// Affects how we spread noise between 'risky' areas (where noise is easily
// visible) and easier areas (where it's less visible). A high SNS
// value leads to skewing noise more towards areas where it should be less
// visible. In general this improves SSIM but worsens PSNR.
float sns = 50.f;
int error_diffusion = 0; // error diffusion strength [0=off, 100=max]
int segments = 4; // Max number of segments. Range: [1..kMaxNumSegments]
int segment_threshold = 0; // Segmentation threshold. Range: [0..100]
// selector for explicit or implicit segment-id
// typedef enum {
// SEGMENT_ID_AUTO, // use ID_EXPLICIT above a quality threshold
// SEGMENT_ID_EXPLICIT,
// SEGMENT_ID_IMPLICIT
// } SegmentIdMode;
// SegmentIdMode segment_id_mode = SEGMENT_ID_AUTO;
// Size of tiles (width/height) in pixels. Tiles are always square. Each
// tile is compressed independently, possibly in parallel.
// Valid values: 64, 128, 256, 512 (see format_constants.h)
// 0 means size is chosen automatically.
int tile_size = 0;
// Algorithm for dividing the image into blocks.
// PartitionMethod partition_method = MULTIPASS_PARTITIONING;
// The set of allowed block sizes for image partitioning.
// PartitionSet partition_set = SOME_RECTS;
// If true, use binary space partitioning instead of floating partition.
bool partition_snapping = true;
// The set of predictors that can be used for reconstruction.
// PredictorSet predictor_set = PredictorSet::VP8_PREDICTORS;
WP2::Csp csp_type = WP2::Csp::kYCoCg; // Colorspace.
WP2::EncoderConfig::UVMode uv_mode =
WP2::EncoderConfig::UVMode::UVMode420; // Default sub-sampling mode for
// U/V planes.
// int preprocessing = 0; // Preprocessing filter.
// int preprocessing_strength = 0; // Range: [0 .. 100]
// bool use_random_matrix = false; // Experimental.
// bool store_grain = false; // Experimental: store grain info
// // Parameters related to lossless compression only:
// bool use_delta_palette = false; // Reserved for future lossless feature.
// // Performance parameters (no impact on encoded bytes):
// int thread_level = 0; // If non-zero, try and use multi-threaded
// encoding. bool low_memory = false; // Memory usage reduction (but CPU use
// increase).
// // Neural compression:
// int use_neural_compression = 0; // Neural network compression.
// const char* graphdef_path = nullptr; // Directory holding encoder /
// decoder
// // graphdefs structure:
// // base/qq/[en|de]coder.pbbin
// EncoderInfo* info = nullptr; // If not
};
val encode(std::string image_in, int image_width, int image_height,
WP2Options options) {
WP2Status status;
uint8_t *image_buffer = (uint8_t *)image_in.c_str();
WP2::ArgbBuffer src = WP2::ArgbBuffer();
status = src.Import(WP2_rgbA_32, // Format. WP2_RGBA_32 is the same but NOT
// premultiplied alpha
image_width, image_height, image_buffer, 4 * image_width);
if (status != WP2_STATUS_OK) {
return val(1);
}
WP2::MemoryWriter memory_writer;
WP2::EncoderConfig config;
config.quality = options.quality;
config.alpha_quality = options.alpha_quality;
config.speed = options.speed;
config.pass = options.pass;
config.sns = options.sns;
status = WP2::Encode(src, &memory_writer, config);
if (status != WP2_STATUS_OK) {
return val(2);
}
return val(typed_memory_view(memory_writer.size_, memory_writer.mem_));
// Lol I forgot to add the free here.
}
EMSCRIPTEN_BINDINGS(my_module) {
value_object<WP2Options>("WP2Options")
.field("quality", &WP2Options::quality)
.field("alpha_quality", &WP2Options::alpha_quality)
.field("speed", &WP2Options::speed)
.field("pass", &WP2Options::pass)
.field("sns", &WP2Options::sns);
function("encode", &encode);
}

8
codecs/wp2/enc/wp2_enc.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
import { EncodeOptions } from '../../src/codecs/wp2/encoder-meta';
interface WP2Module extends EmscriptenWasm.Module {
encode(data: BufferSource, width: number, height: number, options: EncodeOptions): Uint8Array;
free_result(): void;
}
export default function(opts: EmscriptenWasm.ModuleOpts): Promise<WP2Module>;

71
codecs/wp2/enc/wp2_enc.js Normal file
View File

@@ -0,0 +1,71 @@
var wp2_enc = (function() {
var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined;
if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename;
return (
function(wp2_enc) {
wp2_enc = wp2_enc || {};
var c;c||(c=typeof wp2_enc !== 'undefined' ? wp2_enc : {});var aa,ba;c.ready=new Promise(function(a,b){aa=a;ba=b});var r={},t;for(t in c)c.hasOwnProperty(t)&&(r[t]=c[t]);var u=!1,v=!1,ca=!1,da=!1;u="object"===typeof window;v="function"===typeof importScripts;ca="object"===typeof process&&"object"===typeof process.versions&&"string"===typeof process.versions.node;da=!u&&!ca&&!v;var w="",y,B,ea,fa;
if(ca)w=v?require("path").dirname(w)+"/":__dirname+"/",y=function(a,b){ea||(ea=require("fs"));fa||(fa=require("path"));a=fa.normalize(a);return ea.readFileSync(a,b?null:"utf8")},B=function(a){a=y(a,!0);a.buffer||(a=new Uint8Array(a));a.buffer||C("Assertion failed: undefined");return a},1<process.argv.length&&process.argv[1].replace(/\\/g,"/"),process.argv.slice(2),process.on("uncaughtException",function(a){throw a;}),process.on("unhandledRejection",C),c.inspect=function(){return"[Emscripten Module object]"};
else if(da)"undefined"!=typeof read&&(y=function(a){return read(a)}),B=function(a){if("function"===typeof readbuffer)return new Uint8Array(readbuffer(a));a=read(a,"binary");"object"===typeof a||C("Assertion failed: undefined");return a},"undefined"!==typeof print&&("undefined"===typeof console&&(console={}),console.log=print,console.warn=console.error="undefined"!==typeof printErr?printErr:print);else if(u||v)v?w=self.location.href:document.currentScript&&(w=document.currentScript.src),_scriptDir&&
(w=_scriptDir),0!==w.indexOf("blob:")?w=w.substr(0,w.lastIndexOf("/")+1):w="",y=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},v&&(B=function(a){var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)});var ha=c.print||console.log.bind(console),D=c.printErr||console.warn.bind(console);for(t in r)r.hasOwnProperty(t)&&(c[t]=r[t]);r=null;var E;c.wasmBinary&&(E=c.wasmBinary);var noExitRuntime;
c.noExitRuntime&&(noExitRuntime=c.noExitRuntime);"object"!==typeof WebAssembly&&C("no native wasm support detected");var F,ja=new WebAssembly.Table({initial:449,maximum:449,element:"anyfunc"}),ka=!1,la="undefined"!==typeof TextDecoder?new TextDecoder("utf8"):void 0;
function H(a,b,d){var e=b+d;for(d=b;a[d]&&!(d>=e);)++d;if(16<d-b&&a.subarray&&la)return la.decode(a.subarray(b,d));for(e="";b<d;){var f=a[b++];if(f&128){var g=a[b++]&63;if(192==(f&224))e+=String.fromCharCode((f&31)<<6|g);else{var l=a[b++]&63;f=224==(f&240)?(f&15)<<12|g<<6|l:(f&7)<<18|g<<12|l<<6|a[b++]&63;65536>f?e+=String.fromCharCode(f):(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023))}}else e+=String.fromCharCode(f)}return e}
function ma(a,b,d){var e=I;if(0<d){d=b+d-1;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var l=a.charCodeAt(++f);g=65536+((g&1023)<<10)|l&1023}if(127>=g){if(b>=d)break;e[b++]=g}else{if(2047>=g){if(b+1>=d)break;e[b++]=192|g>>6}else{if(65535>=g){if(b+2>=d)break;e[b++]=224|g>>12}else{if(b+3>=d)break;e[b++]=240|g>>18;e[b++]=128|g>>12&63}e[b++]=128|g>>6&63}e[b++]=128|g&63}}e[b]=0}}var na="undefined"!==typeof TextDecoder?new TextDecoder("utf-16le"):void 0;
function oa(a,b){var d=a>>1;for(var e=d+b/2;!(d>=e)&&J[d];)++d;d<<=1;if(32<d-a&&na)return na.decode(I.subarray(a,d));d=0;for(e="";;){var f=K[a+2*d>>1];if(0==f||d==b/2)return e;++d;e+=String.fromCharCode(f)}}function pa(a,b,d){void 0===d&&(d=2147483647);if(2>d)return 0;d-=2;var e=b;d=d<2*a.length?d/2:a.length;for(var f=0;f<d;++f)K[b>>1]=a.charCodeAt(f),b+=2;K[b>>1]=0;return b-e}function qa(a){return 2*a.length}
function ra(a,b){for(var d=0,e="";!(d>=b/4);){var f=L[a+4*d>>2];if(0==f)break;++d;65536<=f?(f-=65536,e+=String.fromCharCode(55296|f>>10,56320|f&1023)):e+=String.fromCharCode(f)}return e}function sa(a,b,d){void 0===d&&(d=2147483647);if(4>d)return 0;var e=b;d=e+d-4;for(var f=0;f<a.length;++f){var g=a.charCodeAt(f);if(55296<=g&&57343>=g){var l=a.charCodeAt(++f);g=65536+((g&1023)<<10)|l&1023}L[b>>2]=g;b+=4;if(b+4>d)break}L[b>>2]=0;return b-e}
function ta(a){for(var b=0,d=0;d<a.length;++d){var e=a.charCodeAt(d);55296<=e&&57343>=e&&++d;b+=4}return b}var M,ua,I,K,J,L,N,va,wa;function xa(a){M=a;c.HEAP8=ua=new Int8Array(a);c.HEAP16=K=new Int16Array(a);c.HEAP32=L=new Int32Array(a);c.HEAPU8=I=new Uint8Array(a);c.HEAPU16=J=new Uint16Array(a);c.HEAPU32=N=new Uint32Array(a);c.HEAPF32=va=new Float32Array(a);c.HEAPF64=wa=new Float64Array(a)}var ya=c.INITIAL_MEMORY||16777216;c.wasmMemory?F=c.wasmMemory:F=new WebAssembly.Memory({initial:ya/65536,maximum:32768});
F&&(M=F.buffer);ya=M.byteLength;xa(M);L[35276]=5384144;function za(a){for(;0<a.length;){var b=a.shift();if("function"==typeof b)b(c);else{var d=b.na;"number"===typeof d?void 0===b.ha?c.dynCall_v(d):c.dynCall_vi(d,b.ha):d(void 0===b.ha?null:b.ha)}}}var Aa=[],Ba=[],Ca=[],Da=[];function Ea(){var a=c.preRun.shift();Aa.unshift(a)}var Fa=Math.ceil,Ga=Math.floor,O=0,Ha=null,P=null;c.preloadedImages={};c.preloadedAudios={};
function C(a){if(c.onAbort)c.onAbort(a);D(a);ka=!0;a=new WebAssembly.RuntimeError("abort("+a+"). Build with -s ASSERTIONS=1 for more info.");ba(a);throw a;}function Ia(a){var b=Q;return String.prototype.startsWith?b.startsWith(a):0===b.indexOf(a)}function Ja(){return Ia("data:application/octet-stream;base64,")}var Q="wp2_enc.wasm";if(!Ja()){var Ka=Q;Q=c.locateFile?c.locateFile(Ka,w):w+Ka}
function La(){try{if(E)return new Uint8Array(E);if(B)return B(Q);throw"both async and sync fetching of the wasm failed";}catch(a){C(a)}}function Ma(){return E||!u&&!v||"function"!==typeof fetch||Ia("file://")?new Promise(function(a){a(La())}):fetch(Q,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+Q+"'";return a.arrayBuffer()}).catch(function(){return La()})}Ba.push({na:function(){Na()}});function Oa(){return 0<Oa.ja}var Pa={};
function Qa(a){for(;a.length;){var b=a.pop();a.pop()(b)}}function Ra(a){return this.fromWireType(N[a>>2])}var R={},S={},Sa={};function Ta(a){if(void 0===a)return"_unknown";a=a.replace(/[^a-zA-Z0-9_]/g,"$");var b=a.charCodeAt(0);return 48<=b&&57>=b?"_"+a:a}function Ua(a,b){a=Ta(a);return(new Function("body","return function "+a+'() {\n "use strict"; return body.apply(this, arguments);\n};\n'))(b)}
function Va(a){var b=Error,d=Ua(a,function(e){this.name=a;this.message=e;e=Error(e).stack;void 0!==e&&(this.stack=this.toString()+"\n"+e.replace(/^Error(:[^\n]*)?\n/,""))});d.prototype=Object.create(b.prototype);d.prototype.constructor=d;d.prototype.toString=function(){return void 0===this.message?this.name:this.name+": "+this.message};return d}var Wa=void 0;
function Xa(a,b,d){function e(k){k=d(k);if(k.length!==a.length)throw new Wa("Mismatched type converter count");for(var h=0;h<a.length;++h)T(a[h],k[h])}a.forEach(function(k){Sa[k]=b});var f=Array(b.length),g=[],l=0;b.forEach(function(k,h){S.hasOwnProperty(k)?f[h]=S[k]:(g.push(k),R.hasOwnProperty(k)||(R[k]=[]),R[k].push(function(){f[h]=S[k];++l;l===g.length&&e(f)}))});0===g.length&&e(f)}
function Ya(a){switch(a){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError("Unknown type size: "+a);}}var Za=void 0;function U(a){for(var b="";I[a];)b+=Za[I[a++]];return b}var $a=void 0;function V(a){throw new $a(a);}
function T(a,b,d){d=d||{};if(!("argPackAdvance"in b))throw new TypeError("registerType registeredInstance requires argPackAdvance");var e=b.name;a||V('type "'+e+'" must have a positive integer typeid pointer');if(S.hasOwnProperty(a)){if(d.ra)return;V("Cannot register type '"+e+"' twice")}S[a]=b;delete Sa[a];R.hasOwnProperty(a)&&(b=R[a],delete R[a],b.forEach(function(f){f()}))}var ab=[],X=[{},{value:void 0},{value:null},{value:!0},{value:!1}];
function bb(a){4<a&&0===--X[a].ia&&(X[a]=void 0,ab.push(a))}function cb(a){switch(a){case void 0:return 1;case null:return 2;case !0:return 3;case !1:return 4;default:var b=ab.length?ab.pop():X.length;X[b]={ia:1,value:a};return b}}function db(a){if(null===a)return"null";var b=typeof a;return"object"===b||"array"===b||"function"===b?a.toString():""+a}
function eb(a,b){switch(b){case 2:return function(d){return this.fromWireType(va[d>>2])};case 3:return function(d){return this.fromWireType(wa[d>>3])};default:throw new TypeError("Unknown float type: "+a);}}function fb(a){var b=Function;if(!(b instanceof Function))throw new TypeError("new_ called with constructor type "+typeof b+" which is not a function");var d=Ua(b.name||"unknownFunctionName",function(){});d.prototype=b.prototype;d=new d;a=b.apply(d,a);return a instanceof Object?a:d}
function gb(a,b){var d=c;if(void 0===d[a].fa){var e=d[a];d[a]=function(){d[a].fa.hasOwnProperty(arguments.length)||V("Function '"+b+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+d[a].fa+")!");return d[a].fa[arguments.length].apply(this,arguments)};d[a].fa=[];d[a].fa[e.la]=e}}
function hb(a,b,d){c.hasOwnProperty(a)?((void 0===d||void 0!==c[a].fa&&void 0!==c[a].fa[d])&&V("Cannot register public name '"+a+"' twice"),gb(a,a),c.hasOwnProperty(d)&&V("Cannot register multiple overloads of a function with the same number of arguments ("+d+")!"),c[a].fa[d]=b):(c[a]=b,void 0!==d&&(c[a].ya=d))}function ib(a,b){for(var d=[],e=0;e<a;e++)d.push(L[(b>>2)+e]);return d}
function Y(a,b){a=U(a);var d=c["dynCall_"+a];for(var e=[],f=1;f<a.length;++f)e.push("a"+f);f="return function dynCall_"+(a+"_"+b)+"("+e.join(", ")+") {\n";f+=" return dynCall(rawFunction"+(e.length?", ":"")+e.join(", ")+");\n";d=(new Function("dynCall","rawFunction",f+"};\n"))(d,b);"function"!==typeof d&&V("unknown function pointer with signature "+a+": "+b);return d}var jb=void 0;function kb(a){a=lb(a);var b=U(a);Z(a);return b}
function mb(a,b){function d(g){f[g]||S[g]||(Sa[g]?Sa[g].forEach(d):(e.push(g),f[g]=!0))}var e=[],f={};b.forEach(d);throw new jb(a+": "+e.map(kb).join([", "]));}function nb(a,b,d){switch(b){case 0:return d?function(e){return ua[e]}:function(e){return I[e]};case 1:return d?function(e){return K[e>>1]}:function(e){return J[e>>1]};case 2:return d?function(e){return L[e>>2]}:function(e){return N[e>>2]};default:throw new TypeError("Unknown integer type: "+a);}}var ob=[null,[],[]];Wa=c.InternalError=Va("InternalError");
for(var pb=Array(256),qb=0;256>qb;++qb)pb[qb]=String.fromCharCode(qb);Za=pb;$a=c.BindingError=Va("BindingError");c.count_emval_handles=function(){for(var a=0,b=5;b<X.length;++b)void 0!==X[b]&&++a;return a};c.get_first_emval=function(){for(var a=5;a<X.length;++a)if(void 0!==X[a])return X[a];return null};jb=c.UnboundTypeError=Va("UnboundTypeError");
var sb={F:function(a,b,d,e){C("Assertion failed: "+(a?H(I,a,void 0):"")+", at: "+[b?b?H(I,b,void 0):"":"unknown filename",d,e?e?H(I,e,void 0):"":"unknown function"])},p:function(a){return rb(a)},o:function(a){"uncaught_exception"in Oa?Oa.ja++:Oa.ja=1;throw a;},u:function(a){var b=Pa[a];delete Pa[a];var d=b.sa,e=b.ta,f=b.ka,g=f.map(function(l){return l.qa}).concat(f.map(function(l){return l.va}));Xa([a],g,function(l){var k={};f.forEach(function(h,m){var n=l[m],q=h.oa,x=h.pa,z=l[m+f.length],p=h.ua,
ia=h.wa;k[h.ma]={read:function(A){return n.fromWireType(q(x,A))},write:function(A,G){var W=[];p(ia,A,z.toWireType(W,G));Qa(W)}}});return[{name:b.name,fromWireType:function(h){var m={},n;for(n in k)m[n]=k[n].read(h);e(h);return m},toWireType:function(h,m){for(var n in k)if(!(n in m))throw new TypeError('Missing field: "'+n+'"');var q=d();for(n in k)k[n].write(q,m[n]);null!==h&&h.push(e,q);return q},argPackAdvance:8,readValueFromPointer:Ra,ga:e}]})},z:function(a,b,d,e,f){var g=Ya(d);b=U(b);T(a,{name:b,
fromWireType:function(l){return!!l},toWireType:function(l,k){return k?e:f},argPackAdvance:8,readValueFromPointer:function(l){if(1===d)var k=ua;else if(2===d)k=K;else if(4===d)k=L;else throw new TypeError("Unknown boolean type size: "+b);return this.fromWireType(k[l>>g])},ga:null})},y:function(a,b){b=U(b);T(a,{name:b,fromWireType:function(d){var e=X[d].value;bb(d);return e},toWireType:function(d,e){return cb(e)},argPackAdvance:8,readValueFromPointer:Ra,ga:null})},j:function(a,b,d){d=Ya(d);b=U(b);T(a,
{name:b,fromWireType:function(e){return e},toWireType:function(e,f){if("number"!==typeof f&&"boolean"!==typeof f)throw new TypeError('Cannot convert "'+db(f)+'" to '+this.name);return f},argPackAdvance:8,readValueFromPointer:eb(b,d),ga:null})},r:function(a,b,d,e,f,g){var l=ib(b,d);a=U(a);f=Y(e,f);hb(a,function(){mb("Cannot call "+a+" due to unbound types",l)},b-1);Xa([],l,function(k){var h=[k[0],null].concat(k.slice(1)),m=k=a,n=f,q=h.length;2>q&&V("argTypes array size mismatch! Must at least get return value and 'this' types!");
for(var x=null!==h[1]&&!1,z=!1,p=1;p<h.length;++p)if(null!==h[p]&&void 0===h[p].ga){z=!0;break}var ia="void"!==h[0].name,A="",G="";for(p=0;p<q-2;++p)A+=(0!==p?", ":"")+"arg"+p,G+=(0!==p?", ":"")+"arg"+p+"Wired";m="return function "+Ta(m)+"("+A+") {\nif (arguments.length !== "+(q-2)+") {\nthrowBindingError('function "+m+" called with ' + arguments.length + ' arguments, expected "+(q-2)+" args!');\n}\n";z&&(m+="var destructors = [];\n");var W=z?"destructors":"null";A="throwBindingError invoker fn runDestructors retType classParam".split(" ");
n=[V,n,g,Qa,h[0],h[1]];x&&(m+="var thisWired = classParam.toWireType("+W+", this);\n");for(p=0;p<q-2;++p)m+="var arg"+p+"Wired = argType"+p+".toWireType("+W+", arg"+p+"); // "+h[p+2].name+"\n",A.push("argType"+p),n.push(h[p+2]);x&&(G="thisWired"+(0<G.length?", ":"")+G);m+=(ia?"var rv = ":"")+"invoker(fn"+(0<G.length?", ":"")+G+");\n";if(z)m+="runDestructors(destructors);\n";else for(p=x?1:2;p<h.length;++p)q=1===p?"thisWired":"arg"+(p-2)+"Wired",null!==h[p].ga&&(m+=q+"_dtor("+q+"); // "+h[p].name+
"\n",A.push(q+"_dtor"),n.push(h[p].ga));ia&&(m+="var ret = retType.fromWireType(rv);\nreturn ret;\n");A.push(m+"}\n");h=fb(A).apply(null,n);p=b-1;if(!c.hasOwnProperty(k))throw new Wa("Replacing nonexistant public symbol");void 0!==c[k].fa&&void 0!==p?c[k].fa[p]=h:(c[k]=h,c[k].la=p);return[]})},b:function(a,b,d,e,f){function g(m){return m}b=U(b);-1===f&&(f=4294967295);var l=Ya(d);if(0===e){var k=32-8*d;g=function(m){return m<<k>>>k}}var h=-1!=b.indexOf("unsigned");T(a,{name:b,fromWireType:g,toWireType:function(m,
n){if("number"!==typeof n&&"boolean"!==typeof n)throw new TypeError('Cannot convert "'+db(n)+'" to '+this.name);if(n<e||n>f)throw new TypeError('Passing a number "'+db(n)+'" from JS side to C/C++ side to an argument of type "'+b+'", which is outside the valid range ['+e+", "+f+"]!");return h?n>>>0:n|0},argPackAdvance:8,readValueFromPointer:nb(b,l,0!==e),ga:null})},a:function(a,b,d){function e(g){g>>=2;var l=N;return new f(M,l[g+1],l[g])}var f=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,
Uint32Array,Float32Array,Float64Array][b];d=U(d);T(a,{name:d,fromWireType:e,argPackAdvance:8,readValueFromPointer:e},{ra:!0})},k:function(a,b){b=U(b);var d="std::string"===b;T(a,{name:b,fromWireType:function(e){var f=N[e>>2];if(d)for(var g=e+4,l=0;l<=f;++l){var k=e+4+l;if(l==f||0==I[k]){g=g?H(I,g,k-g):"";if(void 0===h)var h=g;else h+=String.fromCharCode(0),h+=g;g=k+1}}else{h=Array(f);for(l=0;l<f;++l)h[l]=String.fromCharCode(I[e+4+l]);h=h.join("")}Z(e);return h},toWireType:function(e,f){f instanceof
ArrayBuffer&&(f=new Uint8Array(f));var g="string"===typeof f;g||f instanceof Uint8Array||f instanceof Uint8ClampedArray||f instanceof Int8Array||V("Cannot pass non-string to std::string");var l=(d&&g?function(){for(var m=0,n=0;n<f.length;++n){var q=f.charCodeAt(n);55296<=q&&57343>=q&&(q=65536+((q&1023)<<10)|f.charCodeAt(++n)&1023);127>=q?++m:m=2047>=q?m+2:65535>=q?m+3:m+4}return m}:function(){return f.length})(),k=rb(4+l+1);N[k>>2]=l;if(d&&g)ma(f,k+4,l+1);else if(g)for(g=0;g<l;++g){var h=f.charCodeAt(g);
255<h&&(Z(k),V("String has UTF-16 code units that do not fit in 8 bits"));I[k+4+g]=h}else for(g=0;g<l;++g)I[k+4+g]=f[g];null!==e&&e.push(Z,k);return k},argPackAdvance:8,readValueFromPointer:Ra,ga:function(e){Z(e)}})},e:function(a,b,d){d=U(d);if(2===b){var e=oa;var f=pa;var g=qa;var l=function(){return J};var k=1}else 4===b&&(e=ra,f=sa,g=ta,l=function(){return N},k=2);T(a,{name:d,fromWireType:function(h){for(var m=N[h>>2],n=l(),q,x=h+4,z=0;z<=m;++z){var p=h+4+z*b;if(z==m||0==n[p>>k])x=e(x,p-x),void 0===
q?q=x:(q+=String.fromCharCode(0),q+=x),x=p+b}Z(h);return q},toWireType:function(h,m){"string"!==typeof m&&V("Cannot pass non-string to C++ string type "+d);var n=g(m),q=rb(4+n+b);N[q>>2]=n>>k;f(m,q+4,n+b);null!==h&&h.push(Z,q);return q},argPackAdvance:8,readValueFromPointer:Ra,ga:function(h){Z(h)}})},x:function(a,b,d,e,f,g){Pa[a]={name:U(b),sa:Y(d,e),ta:Y(f,g),ka:[]}},f:function(a,b,d,e,f,g,l,k,h,m){Pa[a].ka.push({ma:U(b),qa:d,oa:Y(e,f),pa:g,va:l,ua:Y(k,h),wa:m})},A:function(a,b){b=U(b);T(a,{xa:!0,
name:b,argPackAdvance:0,fromWireType:function(){},toWireType:function(){}})},n:bb,q:function(a){4<a&&(X[a].ia+=1)},m:function(a,b){var d=S[a];void 0===d&&V("_emval_take_value has unknown type "+kb(a));a=d.readValueFromPointer(b);return cb(a)},h:function(){C()},v:function(a,b,d){I.copyWithin(a,b,b+d)},c:function(a){a>>>=0;var b=I.length;if(2147483648<a)return!1;for(var d=1;4>=d;d*=2){var e=b*(1+.2/d);e=Math.min(e,a+100663296);e=Math.max(16777216,a,e);0<e%65536&&(e+=65536-e%65536);a:{try{F.grow(Math.min(2147483648,
e)-M.byteLength+65535>>>16);xa(F.buffer);var f=1;break a}catch(g){}f=void 0}if(f)return!0}return!1},w:function(){return 0},s:function(){},i:function(a,b,d,e){for(var f=0,g=0;g<d;g++){for(var l=L[b+8*g>>2],k=L[b+(8*g+4)>>2],h=0;h<k;h++){var m=I[l+h],n=ob[a];0===m||10===m?((1===a?ha:D)(H(n,0)),n.length=0):n.push(m)}f+=k}L[e>>2]=f;return 0},memory:F,l:function(){return 0},E:function(){return 0},D:function(){},C:function(){return 6},B:function(){},g:function(a){a=+a;return 0<=a?+Ga(a+.5):+Fa(a-.5)},d:function(a){a=
+a;return 0<=a?+Ga(a+.5):+Fa(a-.5)},t:function(){},table:ja};
(function(){function a(f){c.asm=f.exports;O--;c.monitorRunDependencies&&c.monitorRunDependencies(O);0==O&&(null!==Ha&&(clearInterval(Ha),Ha=null),P&&(f=P,P=null,f()))}function b(f){a(f.instance)}function d(f){return Ma().then(function(g){return WebAssembly.instantiate(g,e)}).then(f,function(g){D("failed to asynchronously prepare wasm: "+g);C(g)})}var e={a:sb};O++;c.monitorRunDependencies&&c.monitorRunDependencies(O);if(c.instantiateWasm)try{return c.instantiateWasm(e,a)}catch(f){return D("Module.instantiateWasm callback failed with error: "+
f),!1}(function(){if(E||"function"!==typeof WebAssembly.instantiateStreaming||Ja()||Ia("file://")||"function"!==typeof fetch)return d(b);fetch(Q,{credentials:"same-origin"}).then(function(f){return WebAssembly.instantiateStreaming(f,e).then(b,function(g){D("wasm streaming compile failed: "+g);D("falling back to ArrayBuffer instantiation");return d(b)})})})();return{}})();
var Na=c.___wasm_call_ctors=function(){return(Na=c.___wasm_call_ctors=c.asm.G).apply(null,arguments)},rb=c._malloc=function(){return(rb=c._malloc=c.asm.H).apply(null,arguments)},Z=c._free=function(){return(Z=c._free=c.asm.I).apply(null,arguments)},lb=c.___getTypeName=function(){return(lb=c.___getTypeName=c.asm.J).apply(null,arguments)};c.___embind_register_native_and_builtin_types=function(){return(c.___embind_register_native_and_builtin_types=c.asm.K).apply(null,arguments)};
c.dynCall_i=function(){return(c.dynCall_i=c.asm.L).apply(null,arguments)};c.dynCall_vi=function(){return(c.dynCall_vi=c.asm.M).apply(null,arguments)};c.dynCall_fii=function(){return(c.dynCall_fii=c.asm.N).apply(null,arguments)};c.dynCall_viif=function(){return(c.dynCall_viif=c.asm.O).apply(null,arguments)};c.dynCall_iii=function(){return(c.dynCall_iii=c.asm.P).apply(null,arguments)};c.dynCall_viii=function(){return(c.dynCall_viii=c.asm.Q).apply(null,arguments)};
c.dynCall_iiiiii=function(){return(c.dynCall_iiiiii=c.asm.R).apply(null,arguments)};c.dynCall_viiiii=function(){return(c.dynCall_viiiii=c.asm.S).apply(null,arguments)};c.dynCall_ii=function(){return(c.dynCall_ii=c.asm.T).apply(null,arguments)};c.dynCall_vii=function(){return(c.dynCall_vii=c.asm.U).apply(null,arguments)};c.dynCall_viiiiiii=function(){return(c.dynCall_viiiiiii=c.asm.V).apply(null,arguments)};c.dynCall_viiiiiiiii=function(){return(c.dynCall_viiiiiiiii=c.asm.W).apply(null,arguments)};
c.dynCall_viiiiiiii=function(){return(c.dynCall_viiiiiiii=c.asm.X).apply(null,arguments)};c.dynCall_viiii=function(){return(c.dynCall_viiii=c.asm.Y).apply(null,arguments)};c.dynCall_viiiiii=function(){return(c.dynCall_viiiiii=c.asm.Z).apply(null,arguments)};c.dynCall_iidiiii=function(){return(c.dynCall_iidiiii=c.asm._).apply(null,arguments)};c.dynCall_v=function(){return(c.dynCall_v=c.asm.$).apply(null,arguments)};c.dynCall_iiiii=function(){return(c.dynCall_iiiii=c.asm.aa).apply(null,arguments)};
c.dynCall_fi=function(){return(c.dynCall_fi=c.asm.ba).apply(null,arguments)};c.dynCall_iiiiiiiiii=function(){return(c.dynCall_iiiiiiiiii=c.asm.ca).apply(null,arguments)};c.dynCall_iiii=function(){return(c.dynCall_iiii=c.asm.da).apply(null,arguments)};c.dynCall_jiji=function(){return(c.dynCall_jiji=c.asm.ea).apply(null,arguments)};var tb;P=function ub(){tb||vb();tb||(P=ub)};
function vb(){function a(){if(!tb&&(tb=!0,c.calledRun=!0,!ka)){za(Ba);za(Ca);aa(c);if(c.onRuntimeInitialized)c.onRuntimeInitialized();if(c.postRun)for("function"==typeof c.postRun&&(c.postRun=[c.postRun]);c.postRun.length;){var b=c.postRun.shift();Da.unshift(b)}za(Da)}}if(!(0<O)){if(c.preRun)for("function"==typeof c.preRun&&(c.preRun=[c.preRun]);c.preRun.length;)Ea();za(Aa);0<O||(c.setStatus?(c.setStatus("Running..."),setTimeout(function(){setTimeout(function(){c.setStatus("")},1);a()},1)):a())}}
c.run=vb;if(c.preInit)for("function"==typeof c.preInit&&(c.preInit=[c.preInit]);0<c.preInit.length;)c.preInit.pop()();noExitRuntime=!0;vb();
return wp2_enc.ready
}
);
})();
if (typeof exports === 'object' && typeof module === 'object')
module.exports = wp2_enc;
else if (typeof define === 'function' && define['amd'])
define([], function() { return wp2_enc; });
else if (typeof exports === 'object')
exports["wp2_enc"] = wp2_enc;

BIN
codecs/wp2/enc/wp2_enc.wasm Normal file

Binary file not shown.

6
codecs/wp2/package.json Normal file
View File

@@ -0,0 +1,6 @@
{
"name": "wp2",
"scripts": {
"build": "../build-cpp.sh"
}
}

View File

@@ -1,12 +1,16 @@
import { builtinDecode, sniffMimeType, canDecodeImageType } from '../lib/util';
import Processor from './processor';
export async function decodeImage(blob: Blob, processor: Processor): Promise<ImageData> {
export async function decodeImage(
blob: Blob,
processor: Processor,
): Promise<ImageData> {
const mimeType = await sniffMimeType(blob);
const canDecode = await canDecodeImageType(mimeType);
try {
if (!canDecode) {
if (mimeType === 'image/webp2') return await processor.wp2Decode(blob);
if (mimeType === 'image/avif') return await processor.avifDecode(blob);
if (mimeType === 'image/webp') return await processor.webpDecode(blob);
if (mimeType === 'image/jpegxl') return await processor.jxlDecode(blob);
@@ -14,6 +18,6 @@ export async function decodeImage(blob: Blob, processor: Processor): Promise<Ima
}
return await builtinDecode(blob);
} catch (err) {
throw Error("Couldn't decode image");
throw Error('Couldnt decode image');
}
}

View File

@@ -2,6 +2,7 @@ import * as identity from './identity/encoder-meta';
import * as oxiPNG from './oxipng/encoder-meta';
import * as mozJPEG from './mozjpeg/encoder-meta';
import * as webP from './webp/encoder-meta';
import * as wp2 from './wp2/encoder-meta';
import * as avif from './avif/encoder-meta';
import * as jxl from './jxl/encoder-meta';
import * as browserPNG from './browser-png/encoder-meta';
@@ -22,6 +23,7 @@ export type EncoderState =
oxiPNG.EncoderState |
mozJPEG.EncoderState |
webP.EncoderState |
wp2.EncoderState |
avif.EncoderState |
jxl.EncoderState |
browserPNG.EncoderState |
@@ -38,6 +40,7 @@ export type EncoderOptions =
oxiPNG.EncodeOptions |
mozJPEG.EncodeOptions |
webP.EncodeOptions |
wp2.EncodeOptions |
avif.EncodeOptions |
jxl.EncodeOptions |
browserPNG.EncodeOptions |
@@ -56,6 +59,7 @@ export const encoderMap = {
[oxiPNG.type]: oxiPNG,
[mozJPEG.type]: mozJPEG,
[webP.type]: webP,
[wp2.type]: wp2,
[avif.type]: avif,
[jxl.type]: jxl,
[browserPNG.type]: browserPNG,

View File

@@ -82,6 +82,22 @@ async function webpDecode(data: ArrayBuffer): Promise<ImageData> {
return timed('webpDecode', () => decode(data));
}
async function wp2Encode(
data: ImageData, options: import('../wp2/encoder-meta').EncodeOptions,
): Promise<ArrayBuffer> {
const { encode } = await import(
/* webpackChunkName: "process-wp2 -enc" */
'../wp2/encoder');
return encode(data, options);
}
async function wp2Decode(data: ArrayBuffer): Promise<ImageData> {
const { decode } = await import(
/* webpackChunkName: "process-wp2-dec" */
'../wp2/decoder');
return decode(data);
}
async function avifEncode(
data: ImageData, options: import('../avif/encoder-meta').EncodeOptions,
): Promise<ArrayBuffer> {
@@ -122,6 +138,8 @@ const exports = {
oxiPngEncode,
webpEncode,
webpDecode,
wp2Encode,
wp2Decode,
avifEncode,
avifDecode,
jxlEncode,

View File

@@ -4,6 +4,7 @@ import { canvasEncode, blobToArrayBuffer } from '../lib/util';
import { EncodeOptions as MozJPEGEncoderOptions } from './mozjpeg/encoder-meta';
import { EncodeOptions as OxiPNGEncoderOptions } from './oxipng/encoder-meta';
import { EncodeOptions as WebPEncoderOptions } from './webp/encoder-meta';
import { EncodeOptions as WP2EncoderOptions } from './wp2/encoder-meta';
import { EncodeOptions as AvifEncoderOptions } from './avif/encoder-meta';
import { EncodeOptions as JXLEncoderOptions } from './jxl/encoder-meta';
import { EncodeOptions as BrowserJPEGOptions } from './browser-jpeg/encoder-meta';
@@ -157,12 +158,23 @@ export default class Processor {
return this._workerApi!.webpEncode(data, opts);
}
@Processor._processingJob({ needsWorker: true })
wp2Encode(data: ImageData, opts: WP2EncoderOptions): Promise<ArrayBuffer> {
return this._workerApi!.wp2Encode(data, opts);
}
@Processor._processingJob({ needsWorker: true })
async webpDecode(blob: Blob): Promise<ImageData> {
const data = await blobToArrayBuffer(blob);
return this._workerApi!.webpDecode(data);
}
@Processor._processingJob({ needsWorker: true })
async wp2Decode(blob: Blob): Promise<ImageData> {
const data = await blobToArrayBuffer(blob);
return this._workerApi!.wp2Decode(data);
}
@Processor._processingJob({ needsWorker: true })
async avifDecode(blob: Blob): Promise<ImageData> {
const data = await blobToArrayBuffer(blob);

View File

@@ -0,0 +1,7 @@
export const name = 'WASM WP2 Decoder';
const supportedMimeTypes = ['image/webp2'];
export function canHandleMimeType(mimeType: string): boolean {
return supportedMimeTypes.includes(mimeType);
}

20
src/codecs/wp2/decoder.ts Normal file
View File

@@ -0,0 +1,20 @@
import wp2_dec, { WP2Module } from '../../../codecs/wp2/dec/wp2_dec';
import wasmUrl from '../../../codecs/wp2/dec/wp2_dec.wasm';
import { initEmscriptenModule } from '../util';
let emscriptenModule: Promise<WP2Module>;
export async function decode(data: ArrayBuffer): Promise<ImageData> {
if (!emscriptenModule) emscriptenModule = initEmscriptenModule(wp2_dec, wasmUrl);
const module = await emscriptenModule;
const rawImage = module.decode(data);
const result = new ImageData(
new Uint8ClampedArray(rawImage.buffer),
rawImage.width,
rawImage.height,
);
module.free_result();
return result;
}

View File

@@ -0,0 +1,20 @@
export interface EncodeOptions {
quality: number;
alpha_quality: number;
speed: number;
pass: number;
sns: number;
}
export interface EncoderState { type: typeof type; options: EncodeOptions; }
export const type = 'wp2';
export const label = 'WP2 (unstable)';
export const mimeType = 'image/webp2';
export const extension = 'wp2';
export const defaultOptions: EncodeOptions = {
quality: 75,
alpha_quality: 100,
speed: 5,
pass: 1,
sns: 50,
};

17
src/codecs/wp2/encoder.ts Normal file
View File

@@ -0,0 +1,17 @@
import wp2_enc, { WP2Module } from '../../../codecs/wp2/enc/wp2_enc';
import wasmUrl from '../../../codecs/wp2/enc/wp2_enc.wasm';
import { EncodeOptions } from './encoder-meta';
import { initEmscriptenModule } from '../util';
let emscriptenModule: Promise<WP2Module>;
export async function encode(data: ImageData, options: EncodeOptions): Promise<ArrayBuffer> {
if (!emscriptenModule) emscriptenModule = initEmscriptenModule(wp2_enc, wasmUrl);
const module = await emscriptenModule;
const resultView = module.encode(data.data, data.width, data.height, options);
const result = new Uint8Array(resultView);
// wasm cant run on SharedArrayBuffers, so we hard-cast to ArrayBuffer.
return result.buffer as ArrayBuffer;
}

109
src/codecs/wp2/options.tsx Normal file
View File

@@ -0,0 +1,109 @@
import { h, Component } from 'preact';
import { bind } from '../../lib/initial-util';
import { inputFieldValueAsNumber, preventDefault } from '../../lib/util';
import { EncodeOptions } from './encoder-meta';
import * as style from '../../components/Options/style.scss';
// import Checkbox from '../../components/checkbox';
// import Expander from '../../components/expander';
// import Select from '../../components/select';
import Range from '../../components/range';
// import linkState from 'linkstate';
interface Props {
options: EncodeOptions;
onChange(newOptions: EncodeOptions): void;
}
interface State {
showAdvanced: boolean;
}
export default class WP2EncoderOptions extends Component<Props, State> {
state: State = {
showAdvanced: false,
};
@bind
onChange(event: Event) {
const form = (event.currentTarget as HTMLInputElement).closest(
'form',
) as HTMLFormElement;
const { options } = this.props;
const newOptions: EncodeOptions = {
quality: inputFieldValueAsNumber(form.quality, options.quality),
alpha_quality: inputFieldValueAsNumber(form.alpha_quality, options.alpha_quality),
speed: inputFieldValueAsNumber(form.speed, options.speed),
pass: inputFieldValueAsNumber(form.pass, options.pass),
sns: inputFieldValueAsNumber(form.sns, options.sns),
};
this.props.onChange(newOptions);
}
render({ options }: Props) {
return (
<form class={style.optionsSection} onSubmit={preventDefault}>
<div class={style.optionOneCell}>
<Range
name="quality"
min="0"
max="100"
step="1"
value={options.quality}
onInput={this.onChange}
>
Quality:
</Range>
</div>
<div class={style.optionOneCell}>
<Range
name="alpha_quality"
min="0"
max="100"
step="1"
value={options.alpha_quality}
onInput={this.onChange}
>
Alpha Quality:
</Range>
</div>
<div class={style.optionOneCell}>
<Range
name="speed"
min="0"
max="9"
step="1"
value={options.speed}
onInput={this.onChange}
>
Speed:
</Range>
</div>
<div class={style.optionOneCell}>
<Range
name="pass"
min="1"
max="10"
step="1"
value={options.pass}
onInput={this.onChange}
>
Pass:
</Range>
</div>
<div class={style.optionOneCell}>
<Range
name="sns"
min="0"
max="100"
step="1"
value={options.sns}
onInput={this.onChange}
>
Spatial noise shaping:
</Range>
</div>
</form>
);
}
}

View File

@@ -7,6 +7,7 @@ import OxiPNGEncoderOptions from '../../codecs/oxipng/options';
import MozJpegEncoderOptions from '../../codecs/mozjpeg/options';
import BrowserJPEGEncoderOptions from '../../codecs/browser-jpeg/options';
import WebPEncoderOptions from '../../codecs/webp/options';
import WP2EncoderOptions from '../../codecs/wp2/options';
import AvifEncoderOptions from '../../codecs/avif/options';
import JXLEncoderOptions from '../../codecs/jxl/options';
import BrowserWebPEncoderOptions from '../../codecs/browser-webp/options';
@@ -18,6 +19,7 @@ import * as identity from '../../codecs/identity/encoder-meta';
import * as oxiPNG from '../../codecs/oxipng/encoder-meta';
import * as mozJPEG from '../../codecs/mozjpeg/encoder-meta';
import * as webP from '../../codecs/webp/encoder-meta';
import * as wp2 from '../../codecs/wp2/encoder-meta';
import * as avif from '../../codecs/avif/encoder-meta';
import * as jxl from '../../codecs/jxl/encoder-meta';
import * as browserPNG from '../../codecs/browser-png/encoder-meta';
@@ -51,6 +53,7 @@ const encoderOptionsComponentMap: {
[oxiPNG.type]: OxiPNGEncoderOptions,
[mozJPEG.type]: MozJpegEncoderOptions,
[webP.type]: WebPEncoderOptions,
[wp2.type]: WP2EncoderOptions,
[avif.type]: AvifEncoderOptions,
[jxl.type]: JXLEncoderOptions,
[browserPNG.type]: undefined,

View File

@@ -10,6 +10,7 @@ import * as identity from '../../codecs/identity/encoder-meta';
import * as oxiPNG from '../../codecs/oxipng/encoder-meta';
import * as mozJPEG from '../../codecs/mozjpeg/encoder-meta';
import * as webP from '../../codecs/webp/encoder-meta';
import * as wp2 from '../../codecs/wp2/encoder-meta';
import * as avif from '../../codecs/avif/encoder-meta';
import * as jxl from '../../codecs/jxl/encoder-meta';
import * as browserPNG from '../../codecs/browser-png/encoder-meta';
@@ -138,6 +139,7 @@ async function compressImage(
case oxiPNG.type: return processor.oxiPngEncode(image, encodeData.options);
case mozJPEG.type: return processor.mozjpegEncode(image, encodeData.options);
case webP.type: return processor.webpEncode(image, encodeData.options);
case wp2.type: return processor.wp2Encode(image, encodeData.options);
case avif.type: return processor.avifEncode(image, encodeData.options);
case jxl.type: return processor.jxlEncode(image, encodeData.options);
case browserPNG.type: return processor.browserPngEncode(image);

View File

@@ -129,6 +129,7 @@ const magicNumberToMimeType = new Map<RegExp, string>([
[/^II*/, 'image/tiff'],
[/^MM\x00*/, 'image/tiff'],
[/^RIFF....WEBPVP8[LX ]/, 'image/webp'],
[/\xF4\xFF\x6F/, 'image/webp2'], // Not sure about this one tho lol
[/^\x00\x00\x00 ftypavif\x00\x00\x00\x00/, 'image/avif'],
[/^\xff\x0a/, 'image/jpegxl'],
]);