diff --git a/dist/boostlet.min.js b/dist/boostlet.min.js index 14c5f40f..fe6363fc 100644 --- a/dist/boostlet.min.js +++ b/dist/boostlet.min.js @@ -384,8 +384,8 @@ class $fbafa14c3ac31938$export$3d6843c2c4a1bd6c extends (0, $bsgU1.Framework) { }; // replace nv canvas with new one originalcanvas.parentNode.replaceChild(newcanvas, originalcanvas); - newcanvas.style.width = originalcanvas.clientWidth; - newcanvas.style.height = originalcanvas.clientHeight; + newcanvas.style.width = originalcanvas.clientWidth + "px"; + newcanvas.style.height = originalcanvas.clientHeight + "px"; } set_mask(new_mask) { // merge image + mask diff --git a/dist/boostlet.min.js.map b/dist/boostlet.min.js.map index 4efd869d..e8b49aa6 100644 --- a/dist/boostlet.min.js.map +++ b/dist/boostlet.min.js.map @@ -1 +1 @@ -{"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKO,MAAM;IAEX,OAAO,mBAAmB;QAExB,IAAI,cAAY;QAEhB,IAAI,KAAK,UAAU,CAAC,OAAO,EAAE,GAE3B,cAAY,IAAI,CAAA,GAAA,aAAK,EAAE,OAAO,EAAE;aAE3B,IAAI,KAAK,UAAU,CAAC,OAAO,MAAM,GAEtC,cAAY,IAAI,CAAA,GAAA,aAAK,EAAE,OAAO,MAAM;aAE/B,IAAI,KAAK,UAAU,CAAC,OAAO,WAAW,GAE3C,cAAY,IAAI,CAAA,GAAA,oBAAY,EAAE,OAAO,WAAW;aAE3C,IAAI,KAAK,UAAU,CAAC,OAAO,aAAa,GAE7C,cAAY,IAAI,CAAA,GAAA,oBAAY,EAAE,OAAO,aAAa;QAIpD,sDAAsD;QAEtD,OAAO;IAET;IAEA,aAAa,YAAY,GAAG,EAAE,QAAQ,EAAE;QAEtC,iDAAiD;QACjD,OAAO,MAAM,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,SAAS,EAAE,UAAU;YAC9D;gBACE,OAAO;YACT;YACA,KAAI,WAAS;gBACX,aAAa;YACf;QACF;QAEA,MAAM,SAAS,OAAO,QAAQ,CAAC,aAAa,CAAC;QAC7C,OAAO,IAAI,GAAG;QACd,OAAO,GAAG,GAAG;QAEb,IAAI,KAAK,UAAU,CAAC,WAClB,OAAO,MAAM,GAAG;QAGlB,OAAO,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC;QACjC,KAAK;IAEP;IAEA,aAAa,eAAe,KAAG,EAAE,MAAI,EAAE,UAAQ,EAAE;QAE/C,IAAI,QAAM,IAAI;QACd,MAAI,IAAI,CAAC,QAAQ;QACjB,MAAI,kBAAkB,GAAG;YACvB,IAAI,MAAI,UAAU,KAAK,GAAG;gBACxB,eAAe;gBACf,WAAU,MAAI,QAAQ;gBAEtB;YAEF;QACF;QAEA,MAAI,IAAI,CAAC;IAEX;IAEA,OAAO,eAAe,YAAU,EAAE,OAAK,EAAE,QAAM,EAAE,MAAI,EAAE;QAErD,4CAA4C;QAC5C,IAAI,cAAY,OAAO,QAAQ,CAAC,aAAa,CAAC;QAC9C,YAAU,KAAK,GAAG;QAClB,YAAU,MAAM,GAAG;QAEnB,IAAI,kBAAgB,YAAU,UAAU,CAAC;QAEzC,IAAI,YAAU,gBAAc,eAAe,CAAC,YAAU,KAAK,EAAE,YAAU,MAAM;QAC7E,IAAI,WAAS,UAAQ,IAAI;QAEzB,IAAK,IAAI,MAAG,GAAG,MAAE,SAAO,MAAM,EAAC,MAE7B,QAAM,CAAC,IAAE,GAAG,YAAU,CAAC,IAAE;QAGzB,8BAA8B;QAChC,gBAAc,YAAY,CAAC,WAAS,GAAG;QAGvC,IAAI,QAAM;YAER,gBAAc,IAAI;YAClB,gBAAc,KAAK,CAAC,GAAG,KAAK,kBAAkB;YAC9C,gBAAc,SAAS,CAAC,aAAW,GAAG,CAAC;YACvC,gBAAc,OAAO;QAEvB;QAEA,IAAI,WAAS,YAAU,SAAS,CAAC;QAEjC,gCAAgC;QAChC,mDAAmD;QACnD,sBAAsB;QACtB,8BAA8B;QAC9B,gBAAgB;QAEhB,WAAS,SAAO,OAAO,CAAC,0BAAyB;QAEjD,IAAI,cAAY,WAAW,IAAI,CAAC,KAAK,WAAS,CAAC,MAAM,IAAE,UAAU,CAAC;QAElE,OAAO;IAET;IAEA,OAAO,OAAO,QAAM,EAAE,OAAK,EAAE,QAAM,EAAE,QAAM,EAAE;QAE3C,MAAM,eAAa,KAAK,IAAI,CAAC,SAAO,MAAM;QAC1C,MAAM,mBAAiB,KAAK,KAAK,CAAC,eAAa;QAE/C,MAAM,eAAa,SAAO,KAAK;QAE/B,IAAK,IAAI,MAAI,GAAG,MAAI,UAAQ,MAC1B,IAAK,IAAI,MAAI,GAAG,MAAI,SAAO,MAAK;YAC9B,MAAM,aAAW,MAAI,UAAQ;YAE7B,IAAI,aAAW;YACf,IAAK,IAAI,OAAK,GAAG,OAAK,cAAY,OAChC,IAAK,IAAI,OAAK,GAAG,OAAK,cAAY,OAAM;gBACtC,MAAM,SAAO,MAAI,OAAK;gBACtB,MAAM,SAAO,MAAI,OAAK;gBACtB,MAAM,aAAW,SAAO,UAAQ;gBAEhC,MAAM,gBAAc,QAAM,CAAC,OAAK,eAAa,KAAG;gBAChD,cAAY,QAAM,CAAC,WAAS,GAAG;YACjC;YAGF,YAAU,CAAC,WAAS,GAAG;QAEzB;QAGF,OAAO;IAET;IAEA,OAAO,kBAAkB,WAAS,EAAE;QAElC,MAAM,SAAO,IAAI,WAAW,YAAU,MAAM,GAAG;QAE/C,IAAK,IAAI,MAAI,GAAG,MAAI,YAAU,MAAM,EAAE,MAAK;YACzC,MAAM,MAAI,WAAS,CAAC,IAAE;YACtB,MAAM,UAAQ,MAAI;YAElB,MAAI,CAAC,QAAM,GAAG;YACd,MAAI,CAAC,UAAQ,EAAE,GAAG;YAClB,MAAI,CAAC,UAAQ,EAAE,GAAG;YAClB,MAAI,CAAC,UAAQ,EAAE,GAAG;QACpB;QAEA,OAAO;IAET;IAEA,OAAO,kBAAkB,MAAI,EAAE;QAE7B,MAAM,cAAY,IAAI,WAAW,OAAK,MAAM,GAAG;QAE/C,IAAK,IAAI,MAAI,GAAG,MAAI,OAAK,MAAM,EAAE,OAAK,EAEpC,WAAS,CAAC,MAAI,EAAE,GAAG,MAAI,CAAC,IAAE;QAI5B,OAAO;IAET;IAEA;;;;;;;;;IASE,GACF,OAAO,YAAY,QAAM,EAAE,MAAI,EAAE,WAAS,EAAE;QAE1C,8JAA8J;QAC9J,qDAAqD;QACrD,uBAAuB;QAGvB,IAAI,eAAa;YAAC;YAAG;YAAK;YAAK;SAAI;QAEnC,IAAI,KAAK,UAAU,CAAC,cAElB,eAAa;QAIf,IAAK,IAAI,MAAI,GAAG,MAAI,OAAK,MAAM,EAAE,MAE/B,IAAI,MAAI,CAAC,IAAE,GAAG,KAAK;YACjB,QAAM,CAAC,IAAI,MAAI,EAAE,GAAG,YAAU,CAAC,EAAE;YACjC,QAAM,CAAC,IAAI,MAAI,EAAE,GAAG,YAAU,CAAC,EAAE;YACjC,QAAM,CAAC,IAAI,MAAI,EAAE,GAAG,YAAU,CAAC,EAAE;YACjC,QAAM,CAAC,IAAI,MAAI,EAAE,GAAG,YAAU,CAAC,EAAE;QACnC;QAIF,OAAO;IAET;IAEA,OAAO,WAAW,UAAQ,EAAE;QAE1B,OAAQ,OAAO,cAAY;IAE7B;AAEF;;;;;;;;ACxOO,MAAM;IAEX,YAAY,QAAQ,CAAE;QAEpB,IAAI,CAAC,IAAI,GAAG;QACZ,IAAI,CAAC,QAAQ,GAAG;QAEhB,IAAI,CAAC,WAAW,GAAG;IAErB;IAEA,UAAU,WAAW,EAAE;QAErB,MAAM;IAER;IAEA,UAAU,UAAU,EAAE;QAEpB,MAAM;IAER;IAEA,SAAS,QAAQ,EAAE;QAEjB,MAAM;IAER;IAEA,WAAW,QAAQ,EAAE;QAEnB,MAAM;IAER;IAEA,eAAe,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE;QAExC,OAAO,CAAA,GAAA,WAAG,EAAE,cAAc,CAAC,YAAY,OAAO,QAAQ,IAAI,CAAC,WAAW;IAExE;AAEF;;;;;;;;;;;ACvCO,MAAM,kDAAsB,CAAA,GAAA,gBAAQ;IAEzC,YAAY,QAAQ,CAAE;QAEpB,KAAK,CAAC;QACN,IAAI,CAAC,IAAI,GAAG;QAEZ,IAAI,CAAC,yBAAyB,GAAG;QAEjC,IAAI,OAAO,OAAO,gBAAgB,IAAI,aAEpC,+BAA+B;QAC/B,IAAI,CAAC,yBAAyB,GAAG,OAAO,gBAAgB;QAI1D,IAAI,CAAC,WAAW,GAAG;IAErB;IAEA,UAAU,WAAW,EAAE;QAErB,IAAI,UAAU,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,EAAE;QACnD,IAAI,SAAS;QACb,IAAI,SAAQ;QACZ,IAAI,UAAS;QAEb,IAAI,OAAO,eAAe,aAAa;YAErC,8CAA8C;YAC9C,yCAAyC;YAEzC,IAAI,SAAS,QAAQ,MAAM;YAC3B,SAAQ,OAAO,KAAK;YACpB,UAAS,OAAO,MAAM;YAEtB,IAAK,MAAM,OAAO,UAAU,CAAC;YAE7B,IAAI,YAAY,IAAI,YAAY,CAAC,GAAG,GAAG,QAAO;YAC9C,SAAS,UAAU,IAAI;QAEzB,OAAO;YAEL,oCAAoC;YACpC,IAAI,YAAY,QAAQ,KAAK;YAC7B,SAAS,UAAU,YAAY;YAC/B,SAAQ,UAAU,KAAK;YACvB,UAAS,UAAU,MAAM;QAE3B;QAEA,OAAO;YAAC,QAAO;YAAQ,SAAQ;YAAO,UAAS;QAAM;IAEvD;IAEA,UAAU,UAAU,EAAE;QAEpB,IAAI,UAAU,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,EAAE;QACnD,IAAI,SAAS,QAAQ,KAAK,CAAC,YAAY;QAEvC,2BAA2B;QAC3B,OAAO,GAAG,CAAC;QAEX,8BAA8B;QAC9B,YAAY,oBAAoB,CAAC,SAAS;IAE5C;IAEA,SAAS,QAAQ,EAAE;QAEjB,sDAAsD;QACtD,mBAAmB;QACnB,0CAA0C;QAE1C,IAAI,UAAU,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,EAAE;QAEnD,IAAI,SAAS,QAAQ,MAAM;QAC3B,QAAQ,OAAO,KAAK;QACpB,SAAS,OAAO,MAAM;QAEtB,IAAI,MAAM,OAAO,UAAU,CAAC;QAE5B,IAAI,YAAY,IAAI,YAAY,CAAC,GAAG,GAAG,OAAO;QAC9C,IAAI,SAAS,UAAU,IAAI;QAE3B,IAAI,eAAe,CAAA,GAAA,WAAG,EAAE,WAAW,CAAC,QAAQ;QAE5C,IAAI,4BAA4B,IAAI,UAAU,cAAc,OAAO;QAEnE,IAAI,YAAY,CAAC,2BAA2B,GAAG;IAEjD;IAEA,WAAW,QAAQ,EAAE;QAEnB,IAAI,CAAC,yBAAyB,CAAC,aAAa,CAAC,gBAAgB;YAAE,iBAAiB;QAAE;QAElF,IAAI,UAAU,IAAI,CAAC,QAAQ,CAAC,kBAAkB,EAAE,CAAC,EAAE;QACnD,IAAI,SAAS,QAAQ,MAAM;QAE3B,OAAO,SAAS,GAAG,CAAA;YAEjB,IAAI,QAAQ,IAAI,CAAC,yBAAyB,CAAC,qCAAqC,CAAC,aAAa;YAE9F,IAAI,UAAU,KAAK,CAAC,OAAO,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK;YAChF,IAAI,cAAc,KAAK,CAAC,OAAO,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG;YAElF,IAAI,YAAY,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,OAAO,EAAE;YAC7D,IAAI,gBAAgB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,OAAO,EAAE;YAEjE,IAAI,CAAC,yBAAyB,CAAC,cAAc,CAAC,QAAQ,OAAO,EAAE;YAC/D,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,SAAS;YAE5C,SAAS,WAAW;QAEtB,CAAA,EAAE,IAAI,CAAC,IAAI;IAEb;AAEF;;;;;;;;;;;ACvHO,MAAM,kDAAe,CAAA,GAAA,gBAAQ;IAElC,YAAY,QAAQ,CAAE;QAEpB,KAAK,CAAC;QACN,IAAI,CAAC,IAAI,GAAG;QAEZ,IAAI,CAAC,WAAW,GAAG;QAEnB,IAAI,CAAC,WAAW,GAAG;QACnB,IAAI,CAAC,EAAE,GAAG;QACV,IAAI,CAAC,EAAE,GAAG;QACV,IAAI,CAAC,EAAE,GAAG;QACV,IAAI,CAAC,EAAE,GAAG;IAEZ;IAEA,UAAU,WAAW,EAAE;QAErB,IAAI,UAAU,IAAI,CAAC,QAAQ,CAAC,MAAM;QAClC,IAAI,SAAS;QACb,IAAI,QAAQ;QACZ,IAAI,SAAS;QAGb,8CAA8C;QAC9C,yCAAyC;QAEzC,IAAI,qBAAqB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc;QAC1D,IAAI,qBAAqB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc;QAE1D,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YAAC;YAAE;YAAE;YAAE;SAAE;QACzC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,GAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,cAAc;QAG5B,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE;QAG1B,QAAQ,IAAI,kBAAkB;QAC9B,SAAS,IAAI,mBAAmB;QAEhC,SAAS,IAAI,WAAW,QAAQ,SAAS;QACzC,IAAI,UAAU,CACZ,GACA,GACA,OACA,QACA,IAAI,IAAI,EACR,IAAI,aAAa,EACjB;QAEF,qBAAqB;QACrB,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAChC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,GAAG;QAEpC,IAAI,CAAC,CAAA,GAAA,WAAG,EAAE,UAAU,CAAC,cAEnB,mCAAmC;QACnC,SAAS,CAAA,GAAA,WAAG,EAAE,iBAAiB,CAAC;QAelC,OAAO;YAAC,QAAO;YAAQ,SAAQ;YAAO,UAAS;QAAM;IAEvD;IAEA;;;;IAIE,GACF,UAAU,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE;QAEtC,iEAAiE;QACjE,oBAAoB;QACpB,uBAAuB;QACvB,cAAc;QACd,gBAAgB;QAEhB,IAAI,iBAAiB,IAAI,CAAC,QAAQ,CAAC,MAAM;QAEzC,IAAI,YAAY,OAAO,QAAQ,CAAC,aAAa,CAAC;QAC9C,UAAU,KAAK,GAAG,eAAe,KAAK;QACtC,UAAU,MAAM,GAAG,eAAe,MAAM;QAExC,sBAAsB;QACtB,IAAI,MAAM,UAAU,UAAU,CAAC;QAE/B,IAAI,kBAAkB;QAEtB,IAAI,CAAA,GAAA,WAAG,EAAE,UAAU,CAAC,UAElB,kBAAkB;aAIlB,kBAAkB,CAAA,GAAA,WAAG,EAAE,iBAAiB,CAAC;QAK3C,IAAI,qBAAqB,IAAI,kBAAkB;QAE/C,IAAI,iBAAiB,IAAI,UAAU,oBAAoB,UAAU,KAAK,EAAE,UAAU,MAAM;QAGxF,IAAI,YAAY,CAAC,gBAAgB,GAAG;QAEpC,IAAI,CAAC,CAAA,GAAA,WAAG,EAAE,UAAU,CAAC,UAAU;YAC7B,uBAAuB;YACvB,IAAI,IAAI;YACR,IAAI,KAAK,CAAC,GAAG;YACb,IAAI,SAAS,CAAC,WAAW,GAAG,CAAC,UAAU,MAAM;YAC7C,IAAI,OAAO;QACb;QAGA,UAAU,OAAO,GAAG;YAElB,0CAA0C;YAC1C,UAAU,UAAU,CAAC,YAAY,CAAC,gBAAgB;QAEpD;QAEA,iCAAiC;QACjC,eAAe,UAAU,CAAC,YAAY,CAAC,WAAW;QAClD,UAAU,KAAK,CAAC,KAAK,GAAG,eAAe,WAAW;QAClD,UAAU,KAAK,CAAC,MAAM,GAAG,eAAe,YAAY;IAEtD;IAEA,SAAS,QAAQ,EAAE;QAEjB,qBAAqB;QACrB,gDAAgD;QAEhD,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC;QAE3B,yDAAyD;QACzD,uDAAuD;QACvD,uBAAuB;QACvB,IAAI,iBAAiB,IAAI,CAAC,QAAQ,CAAC,MAAM;QAEzC,IAAI,YAAY,OAAO,QAAQ,CAAC,aAAa,CAAC;QAC9C,UAAU,KAAK,GAAG,eAAe,KAAK;QACtC,UAAU,MAAM,GAAG,eAAe,MAAM;QACxC,sBAAsB;QACtB,IAAI,MAAM,UAAU,UAAU,CAAC;QAC/B,IAAI,eAAe,IAAI,kBAAkB,MAAM,IAAI;QACnD,IAAI,YAAY,IAAI,UAAU,cAAc,MAAM,KAAK,EAAE,MAAM,MAAM;QACrE,IAAI,YAAY,CAAC,WAAW,GAAG;QAC/B,IAAI,IAAI;QACR,IAAI,KAAK,CAAC,GAAG;QACb,IAAI,SAAS,CAAC,WAAW,GAAG,CAAC,UAAU,MAAM;QAC7C,IAAI,OAAO;QACX,QAAQ,IAAI,YAAY,CAAC,GAAG,GAAG,UAAU,KAAK,EAAE,UAAU,MAAM;QAChE,cAAc;QAEd,IAAI,eAAe,CAAA,GAAA,WAAG,EAAE,WAAW,CAAC,MAAM,IAAI,EAAE;QAEhD,IAAI,CAAC,SAAS,CAAC,cAAc,MAAM,OAAO,qBAAqB;IAGjE;IAEA,WAAW,QAAQ,EAAE;QAEnB,mDAAmD;QAEnD,IAAI,SAAS,IAAI,CAAC,QAAQ,CAAC,MAAM;QAGjC,OAAO,gBAAgB,CAAC,aAAa,CAAA,SAAU,CAAC;YAC9C,IAAI,CAAC,WAAW,GAAG;YAEnB,IAAI,OAAO,EAAE,aAAa,CAAC,qBAAqB,IAChD,UAAU,EAAE,OAAO,GAAG,KAAK,IAAI,EAC/B,UAAU,EAAE,OAAO,GAAG,KAAK,GAAG;YAE9B,IAAI,CAAC,EAAE,GAAG;YACV,IAAI,CAAC,EAAE,GAAG;QACZ,CAAA,EAAE,IAAI,CAAC,IAAI;QAEX,OAAO,gBAAgB,CAAC,aAAa,CAAA,SAAU,CAAC;YAC9C,IAAI,IAAI,CAAC,WAAW,EAAE;gBAEpB,IAAI,OAAO,EAAE,aAAa,CAAC,qBAAqB,IAChD,UAAU,EAAE,OAAO,GAAG,KAAK,IAAI,EAC/B,UAAU,EAAE,OAAO,GAAG,KAAK,GAAG;gBAE9B,IAAI,CAAC,EAAE,GAAG;gBACV,IAAI,CAAC,EAAE,GAAG;gBACV,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC;oBAAC,IAAI,CAAC,EAAE;oBAAE,IAAI,CAAC,EAAE;oBAAE,IAAI,CAAC,EAAE,GAAC,IAAI,CAAC,EAAE;oBAAE,IAAI,CAAC,EAAE,GAAC,IAAI,CAAC,EAAE;iBAAC;YACrF;QACF,CAAA,EAAE,IAAI,CAAC,IAAI;QAGX,OAAO,gBAAgB,CAAC,WAAW,CAAA,SAAU,CAAC;YAC5C,IAAI,OAAO,EAAE,aAAa,CAAC,qBAAqB,IAChD,UAAU,EAAE,OAAO,GAAG,KAAK,IAAI,EAC/B,UAAU,EAAE,OAAO,GAAG,KAAK,GAAG;YAE9B,IAAI,CAAC,EAAE,GAAG;YACV,IAAI,CAAC,EAAE,GAAG;YACV,IAAI,CAAC,WAAW,GAAG;YAEnB,IAAI,UAAU;gBAAC,GAAG,IAAI,CAAC,EAAE;gBAAE,GAAG,IAAI,CAAC,EAAE;YAAA;YACrC,IAAI,cAAc;gBAAC,GAAG,IAAI,CAAC,EAAE;gBAAE,GAAG,IAAI,CAAC,EAAE;YAAA;YAEzC,SAAS,SAAS;QAEpB,CAAA,EAAE,IAAI,CAAC,IAAI;IAEb;AAEF;;;;;;;;;;;ACnOO,MAAM,gDAAsB,CAAA,GAAA,gBAAQ;IACvC,YAAY,QAAQ,CAAE;QAClB,KAAK,CAAC;QACN,IAAI,CAAC,IAAI,GAAG;IAEhB;IAEA,UAAU,WAAW,EAAE;QAGnB,2DAA2D;QAE3D,IAAI,SAAS;QACb,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,QAAQ;QAC/B,GAAG,OAAO,CAAC,SAAS,CAAC;YACjB,IAAI,EAAE,EAAE,IAAI,UACZ,SAAS;QAEb;QAEA,IAAI,CAAC,QACD,MAAM;QAGV,IAAI,SAAS,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE;QACtC,IAAI,MAAM,OAAO,UAAU,CAAC;QAE5B,IAAI,SAAQ,IAAI,YAAY,CAAC,GAAG,GAAG,OAAO,KAAK,EAAE,OAAO,MAAM;QAC9D,IAAI,aAAa,CAAA,GAAA,WAAG,EAAE,iBAAiB,CAAC,OAAM,IAAI;QAClD,IAAI,SAAS,OAAM,IAAI;QAEvB,IAAG,aACC,OAAO;YAAC,QAAO;YAAQ,SAAQ,OAAM,KAAK;YAAE,UAAS,OAAM,MAAM;QAAA;aAGjE,OAAO;YAAC,QAAO;YAAY,SAAQ,OAAM,KAAK;YAAE,UAAS,OAAM,MAAM;QAAA;IAG7E;IAEA,UAAU,UAAU,EAAE;QAElB,IAAI,SAAS;QACb,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,QAAQ;QAC/B,GAAG,OAAO,CAAC,SAAS,CAAC;YACjB,IAAI,EAAE,EAAE,IAAI,UACZ,SAAS;QAEb;QAEA,IAAI,CAAC,QACD,MAAM;QAGV,IAAI,SAAS,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE;QACtC,IAAI,MAAM,OAAO,UAAU,CAAC;QAC5B,IAAI,YAAY,IAAI,UAAU,IAAI,kBAAkB,CAAA,GAAA,WAAG,EAAE,iBAAiB,CAAC,cAAc,MAAM,KAAK,EAAE,MAAM,MAAM;QAElH,IAAI,YAAY,CAAC,WAAW,GAAG;IAEnC;IAEA,SAAS,QAAQ,EAAE;QAEf,IAAI,SAAS;QACb,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,QAAQ;QAC/B,GAAG,OAAO,CAAC,SAAS,CAAC;YACjB,IAAI,EAAE,EAAE,IAAI,UACZ,SAAS;QAEb;QAEA,IAAI,CAAC,QACD,MAAM;QAGV,IAAI,SAAS,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE;QACtC,QAAQ,OAAO,KAAK;QACpB,SAAS,OAAO,MAAM;QAEtB,IAAI,MAAM,OAAO,UAAU,CAAC;QAC5B,IAAI,YAAY,IAAI,YAAY,CAAC,GAAG,GAAG,OAAO;QAC9C,IAAI,SAAS,UAAU,IAAI;QAE3B,IAAI,eAAe,CAAA,GAAA,WAAG,EAAE,WAAW,CAAC,QAAQ;QAE5C,6BAA6B;QAE7B,IAAI,4BAA4B,IAAI,UAAU,cAAc,OAAO;QAEnE,0CAA0C;QAE1C,IAAI,YAAY,CAAC,2BAA2B,GAAG;IAGnD;IAEA,WAAW,QAAQ,EAAE;QAGjB,uFAAuF;QACzF,IAAI,eAAe;QACnB,IAAI,IAAI,IAAI,IAAI;QAEhB,2CAA2C;QAC3C,SAAS,YAAY,KAAK;YACxB,IAAI,cAAc;gBAChB,uCAAuC;gBACvC,KAAK,MAAM,OAAO;gBAClB,KAAK,MAAM,OAAO;gBAClB,QAAQ,GAAG,CAAC,CAAC,kBAAkB,EAAE,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;gBACjD,eAAe;YACjB,OAAO;gBACL,wCAAwC;gBACxC,KAAK,MAAM,OAAO;gBAClB,KAAK,MAAM,OAAO;gBAClB,QAAQ,GAAG,CAAC,CAAC,mBAAmB,EAAE,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC;gBAClD,eAAe;gBAEb,IAAI,UAAU;oBAAC,GAAG;oBAAI,GAAG;gBAAE;gBAC3B,IAAI,cAAc;oBAAC,GAAG;oBAAI,GAAG;gBAAE;gBAE/B,SAAS,SAAS;YACtB;QAEA,kCAAkC;QAClC,sCAAsC;QACtC,kCAAkC;QAEpC;QAGA,6CAA6C;QAC7C,SAAS,gBAAgB,CAAC,SAAS;IAGrC;AAIJ;;;;;;;;AE5IO,MAAM;IAEX,aAAc;QAEZ,IAAI,CAAC,SAAS,GAAG;IAEnB;IAEA;;;;;;;;;GASC,GACD,KAAK,IAAI,EAAE,QAAQ,EAAE;QAEnB,IAAI,OAAO,QAAQ,eAAe,OAAO,YAAY,aAAa;YAEhE,QAAQ,GAAG,CAAC;YACZ,MAAM;QACN,OAAO;QAET,OAEE,IAAI,CAAC,SAAS,GAAG,CAAA,GAAA,WAAG,EAAE,gBAAgB;QAIxC,IAAI,IAAI,CAAC,SAAS,EAEhB,QAAQ,GAAG,CAAC,SAAS,IAAI,CAAC,SAAS,EAAE;aAIrC,MAAM;IAIV;IAEA;;GAEC,GACD,MAAM,WAAW,QAAQ,EAAE;QAEzB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;IAE5B;IAEA;;GAEC,GACD,MAAM,YAAY,OAAO,EAAE;QAEzB,MAAM;IAER;IAEA;;GAEC,GACD,MAAM,YAAY,GAAG,EAAE,QAAQ,EAAE;QAE/B,CAAA,GAAA,WAAG,EAAE,WAAW,CAAC,KAAK;IAExB;IAEA;;GAEC,GACD,MAAM,eAAe,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE;QAExC,CAAA,GAAA,WAAG,EAAE,cAAc,CAAC,KAAK,MAAM;IAEjC;IAEA;;;;;GAKC,GACD,UAAU,WAAW,EAAE;QAErB,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;IAElC;IAEA;;;GAGC,GACD,UAAU,UAAU,EAAE;QAEpB,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;IAElC;IAEA;;;GAGC,GACD,SAAS,QAAQ,EAAE;QAEjB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;IAEjC;IAEA;;GAEC,GACD,eAAe,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE;QAExC,OAAO,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,YAAY,OAAO;IAE1D;IAEA,OAAO,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE;QAEpC,OAAO,CAAA,GAAA,WAAG,EAAE,MAAM,CAAC,QAAQ,OAAO,QAAQ;IAE5C;AAEF;;;ADhIA,OAAO,OAAO,CAAC,GAAG,CAAC;AAEnB,yDAAyD;AACzD,2DAA2D;AAC3D,OAAO,QAAQ,GAAG,IAAI,CAAA,GAAA,wCAAO","sources":["src/util.js","src/framework.js","src/frameworks/cornerstone2d.js","src/frameworks/niivue.js","src/frameworks/openseadragon.js","src/index.js","src/boostlet.js"],"sourcesContent":["import {Framework} from './framework.js';\nimport {Cornerstone2D} from './frameworks/cornerstone2d.js';\nimport {NiiVue} from './frameworks/niivue.js';\nimport { OpenSeaDragon } from './frameworks/openseadragon.js';\n\nexport class Util {\n \n static detect_framework() {\n\n let framework = null;\n\n if (Util.is_defined(window.nv)) {\n \n framework = new NiiVue(window.nv);\n \n } else if (Util.is_defined(window.niivue)) {\n \n framework = new NiiVue(window.niivue);\n\n } else if (Util.is_defined(window.cornerstone)) {\n\n framework = new Cornerstone2D(window.cornerstone);\n\n } else if (Util.is_defined(window.OpenSeadragon)) {\n\n framework = new OpenSeaDragon(window.OpenSeadragon);\n \n }\n\n // TODO: fallback to general canvas or webgl framework\n\n return framework;\n\n }\n\n static async load_script(url, callback) {\n\n // introducing hack to make it work for openneuro\n window.Object.defineProperty(window.Object.prototype, 'global', {\n get( ){\n return window;\n },\n set(newGlobal) {\n globalThis = newGlobal;\n }\n });\n\n const script = window.document.createElement(\"script\")\n script.type = \"text/javascript\"\n script.src = url;\n\n if (Util.is_defined(callback)) {\n script.onload = callback;\n }\n\n window.document.head.appendChild(script);\n eval(script);\n\n }\n\n static async send_http_post(url, data, callback) {\n\n let xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url);\n xhr.onreadystatechange = function () {\n if (xhr.readyState === 4) {\n // request done\n callback( xhr.response );\n\n return;\n\n }\n }\n\n xhr.send(data)\n\n }\n\n static convert_to_png(uint8array, width, height, flip) {\n\n // we are using an offscreen canvas for this\n let offscreen = window.document.createElement('canvas');\n offscreen.width = width;\n offscreen.height = height;\n\n let offscreen_ctx = offscreen.getContext('2d');\n\n let imgdata = offscreen_ctx.createImageData(offscreen.width, offscreen.height);\n let pxdata = imgdata.data;\n\n for (var i =0; i c.charCodeAt(0));\n\n return pngpixels;\n\n }\n\n static filter(pixels, width, height, kernel) {\n\n const kernelSize = Math.sqrt(kernel.length);\n const halfKernelSize = Math.floor(kernelSize / 2);\n\n const new_pixels = pixels.slice();\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const dstIndex = y * width + x;\n\n let newValue = 0;\n for (let ky = 0; ky < kernelSize; ky++) {\n for (let kx = 0; kx < kernelSize; kx++) {\n const srcX = x + kx - halfKernelSize;\n const srcY = y + ky - halfKernelSize;\n const srcIndex = srcY * width + srcX;\n\n const kernelValue = kernel[ky * kernelSize + kx];\n newValue += pixels[srcIndex] * kernelValue;\n }\n }\n\n new_pixels[dstIndex] = newValue;\n\n }\n }\n\n return new_pixels;\n\n }\n\n static grayscale_to_rgba(grayscale) {\n\n const rgba = new Uint8Array(grayscale.length * 4);\n\n for (let i = 0; i < grayscale.length; i++) {\n const g = grayscale[i];\n const index = i * 4;\n\n rgba[index] = g;\n rgba[index + 1] = g;\n rgba[index + 2] = g;\n rgba[index + 3] = 255; \n }\n\n return rgba;\n\n }\n\n static rgba_to_grayscale(rgba) {\n\n const grayscale = new Uint8Array(rgba.length / 4);\n\n for (let i = 0; i < rgba.length; i += 4) {\n\n grayscale[i / 4] = rgba[i];\n\n }\n\n return grayscale;\n\n }\n\n /**\n * Harden a mask into a grayscale pixel array.\n * \n * pixels needs to be RGBA\n * \n * and mask binary.\n * \n * maskcolor is optional and falls back to blue.\n * \n **/\n static harden_mask(pixels, mask, maskcolor) {\n\n // Modified from: https://github.com/facebookresearch/segment-anything/blob/40df6e4046d8b07ab8c4519e083408289eb43032/demo/src/components/helpers/maskUtils.tsx\n // Copyright (c) Meta Platforms, Inc. and affiliates.\n // All rights reserved.\n\n\n let maskcolor_ = [0, 114, 189, 255];\n\n if (Util.is_defined(maskcolor)) {\n \n maskcolor_ = maskcolor;\n \n } \n\n for (var i = 0; i < mask.length; i++) {\n\n if (mask[i] > 0.0) {\n pixels[4 * i + 0] = maskcolor_[0];\n pixels[4 * i + 1] = maskcolor_[1];\n pixels[4 * i + 2] = maskcolor_[2];\n pixels[4 * i + 3] = maskcolor_[3];\n }\n\n }\n\n return pixels;\n\n }\n\n static is_defined(variable) {\n\n return (typeof variable != 'undefined');\n\n }\n\n}","import {Util} from './util.js';\n\nexport class Framework {\n\n constructor(instance) {\n\n this.name = 'generic';\n this.instance = instance;\n\n this.flip_on_png = false;\n\n }\n\n get_image(from_canvas) {\n\n throw \"Missing Implementation.\";\n\n }\n\n set_image(new_pixels) {\n\n throw \"Missing Implementation.\";\n\n }\n\n set_mask(new_mask) {\n\n throw \"Missing Implementation.\";\n \n }\n\n select_box(callback) {\n\n throw \"Missing Implementation.\";\n\n }\n\n convert_to_png(uint8array, width, height) {\n\n return Util.convert_to_png(uint8array, width, height, this.flip_on_png);\n\n }\n\n}\n","import {Framework} from '../framework.js';\n\nimport {Util} from '../util.js';\n\nexport class Cornerstone2D extends Framework {\n \n constructor(instance) {\n\n super(instance);\n this.name = 'cornerstone2D';\n\n this.cornerstonetools_instance = null;\n\n if (typeof window.cornerstoneTools != 'undefined') {\n\n // TODO probably not too robust\n this.cornerstonetools_instance = window.cornerstoneTools;\n\n }\n\n this.flip_on_png = false;\n\n }\n\n get_image(from_canvas) {\n\n let element = this.instance.getEnabledElements()[0];\n let pixels = null;\n let width = null;\n let height = null;\n\n if (typeof from_canvas != 'undefined') {\n\n // TODO this is hacky going through the canvas\n // later should grab the real volume data\n\n let canvas = element.canvas;\n width = canvas.width;\n height = canvas.height;\n\n let ctx = canvas.getContext('2d');\n\n let imagedata = ctx.getImageData(0, 0, width, height);\n pixels = imagedata.data;\n\n } else {\n\n // this is the real image slice data\n let imagedata = element.image;\n pixels = imagedata.getPixelData();\n width = imagedata.width;\n height = imagedata.height;\n\n }\n\n return {'data':pixels, 'width':width, 'height':height};\n\n }\n\n set_image(new_pixels) {\n\n let element = this.instance.getEnabledElements()[0];\n let pixels = element.image.getPixelData();\n\n // Set the new pixel values\n pixels.set(new_pixels);\n\n // Re-render the current slice\n cornerstone.renderGrayscaleImage(element, true);\n\n }\n\n set_mask(new_mask) {\n\n // TODO this needs to use segmentation/labelmap layers\n // from cornerstone\n // right now, this is modifying the canvas\n\n let element = this.instance.getEnabledElements()[0];\n\n let canvas = element.canvas;\n width = canvas.width;\n height = canvas.height;\n\n let ctx = canvas.getContext('2d');\n\n let imagedata = ctx.getImageData(0, 0, width, height);\n let pixels = imagedata.data;\n\n let masked_image = Util.harden_mask(pixels, new_mask);\n\n let masked_image_as_imagedata = new ImageData(masked_image, width, height);\n\n ctx.putImageData(masked_image_as_imagedata, 0, 0);\n \n }\n\n select_box(callback) {\n\n this.cornerstonetools_instance.setToolActive('RectangleRoi', { mouseButtonMask: 1 })\n\n let element = this.instance.getEnabledElements()[0];\n let canvas = element.canvas;\n\n canvas.onmouseup = function() {\n\n let state = this.cornerstonetools_instance.globalImageIdSpecificToolStateManager.saveToolState();\n\n let topleft = state[Object.keys(state).pop()].RectangleRoi.data[0].handles.start;\n let bottomright = state[Object.keys(state).pop()].RectangleRoi.data[0].handles.end;\n\n let topleft_c = this.instance.pixelToCanvas(element.element, topleft);\n let bottomright_c = this.instance.pixelToCanvas(element.element, bottomright);\n\n this.cornerstonetools_instance.clearToolState(element.element, 'RectangleRoi');\n this.instance.renderGrayscaleImage(element, true);\n\n callback(topleft_c, bottomright_c);\n\n }.bind(this);\n\n }\n\n}\n","import {Framework} from '../framework.js';\n\nimport {Util} from '../util.js';\n\nexport class NiiVue extends Framework {\n \n constructor(instance) {\n\n super(instance);\n this.name = 'niivue';\n\n this.flip_on_png = true;\n\n this.onMouseDown = false;\n this.x1 = null;\n this.y1 = null;\n this.x2 = null;\n this.y2 = null;\n\n }\n\n get_image(from_canvas) {\n\n let element = this.instance.canvas;\n let pixels = null;\n let width = null;\n let height = null;\n\n\n // TODO this is hacky going through the canvas\n // later should grab the real volume data\n\n let old_crosshaircolor = this.instance.opts.crosshairColor;\n let old_crosshairwidth = this.instance.opts.crosshairWidth;\n\n this.instance.setCrosshairColor([0,0,0,0]);\n this.instance.opts.crosshairWidth=0;\n this.instance.updateGLVolume();\n\n\n let ctx = this.instance.gl;\n\n \n width = ctx.drawingBufferWidth;\n height = ctx.drawingBufferHeight;\n\n pixels = new Uint8Array(width * height * 4);\n ctx.readPixels(\n 0, \n 0, \n width, \n height, \n ctx.RGBA, \n ctx.UNSIGNED_BYTE, \n pixels);\n\n // restore crosshairs\n this.instance.setCrosshairColor(old_crosshaircolor);\n this.instance.opts.crosshairWidth = old_crosshairwidth;\n\n if (!Util.is_defined(from_canvas)) {\n\n // convert rgba pixels to grayscale\n pixels = Util.rgba_to_grayscale(pixels);\n\n } else {\n\n // TODO\n // not easily possible yet\n // we could hack it using \n // nv.back.get_value(x,y,z)\n // based on the dimensions\n // nv.back.dims.slice(1);\n // but devs promised easy access in the future\n\n }\n\n\n return {'data':pixels, 'width':width, 'height':height};\n\n }\n\n /**\n * Sets the NiiVue.js image.\n * \n * If is_rgba==true, we do *not* convert to RGBA before setting on canvas.\n **/\n set_image(new_pixels, is_rgba, no_flip) {\n\n // TODO this is hacky since we dont work with the real volume yet\n // create new canvas\n // put pixels on canvas\n // show canvas\n // hide on click\n\n let originalcanvas = this.instance.canvas;\n\n let newcanvas = window.document.createElement('canvas');\n newcanvas.width = originalcanvas.width;\n newcanvas.height = originalcanvas.height;\n\n // put new_pixels down\n let ctx = newcanvas.getContext('2d');\n\n let new_pixels_rgba = null;\n\n if (Util.is_defined(is_rgba)) {\n\n new_pixels_rgba = new_pixels;\n\n } else {\n\n new_pixels_rgba = Util.grayscale_to_rgba(new_pixels);\n\n\n }\n\n let new_pixels_clamped = new Uint8ClampedArray(new_pixels_rgba);\n\n let new_image_data = new ImageData(new_pixels_clamped, newcanvas.width, newcanvas.height);\n \n\n ctx.putImageData(new_image_data, 0, 0);\n\n if (!Util.is_defined(no_flip)) {\n // some flipping action\n ctx.save();\n ctx.scale(1, -1);\n ctx.drawImage(newcanvas, 0, -newcanvas.height);\n ctx.restore();\n }\n\n\n newcanvas.onclick = function() {\n\n // on click, we will restore the nv canvas\n newcanvas.parentNode.replaceChild(originalcanvas, newcanvas);\n\n }\n\n // replace nv canvas with new one\n originalcanvas.parentNode.replaceChild(newcanvas, originalcanvas);\n newcanvas.style.width = originalcanvas.clientWidth;\n newcanvas.style.height = originalcanvas.clientHeight;\n\n }\n\n set_mask(new_mask) {\n\n // merge image + mask\n // and then call set_image with that information\n\n let image = this.get_image(true);\n\n // TODO here we need to flip one more time, this is until\n // we use the official niivue infrastructure for adding\n // a segmentation layer\n let originalcanvas = this.instance.canvas;\n\n let newcanvas = window.document.createElement('canvas');\n newcanvas.width = originalcanvas.width;\n newcanvas.height = originalcanvas.height;\n // put new_pixels down\n let ctx = newcanvas.getContext('2d');\n let imageclamped = new Uint8ClampedArray(image.data);\n let imagedata = new ImageData(imageclamped, image.width, image.height);\n ctx.putImageData(imagedata, 0, 0);\n ctx.save();\n ctx.scale(1, -1);\n ctx.drawImage(newcanvas, 0, -newcanvas.height);\n ctx.restore();\n image = ctx.getImageData(0, 0, newcanvas.width, newcanvas.height);\n // end of flip\n\n let masked_image = Util.harden_mask(image.data, new_mask);\n\n this.set_image(masked_image, true, true); // rgba data, no flip\n\n\n }\n\n select_box(callback) {\n\n // TODO also hacky until official API supports this\n\n let canvas = this.instance.canvas;\n\n\n canvas.addEventListener('mousedown', function (e) {\n this.isMouseDown = true;\n\n var rect = e.currentTarget.getBoundingClientRect(),\n offsetX = e.clientX - rect.left,\n offsetY = e.clientY - rect.top;\n\n this.x1 = offsetX;\n this.y1 = offsetY;\n }.bind(this));\n\n canvas.addEventListener('mousemove', function (e) {\n if (this.isMouseDown) {\n\n var rect = e.currentTarget.getBoundingClientRect(),\n offsetX = e.clientX - rect.left,\n offsetY = e.clientY - rect.top;\n\n this.x2 = offsetX;\n this.y2 = offsetY;\n this.instance.drawSelectionBox([this.x1, this.y1, this.x2-this.x1, this.y2-this.y1]);\n }\n }.bind(this));\n\n\n canvas.addEventListener('mouseup', function (e) {\n var rect = e.currentTarget.getBoundingClientRect(),\n offsetX = e.clientX - rect.left,\n offsetY = e.clientY - rect.top;\n \n this.x2 = offsetX;\n this.y2 = offsetY;\n this.isMouseDown = false;\n\n let topleft = {x: this.x1, y: this.y1};\n let bottomright = {x: this.x2, y: this.y2};\n\n callback(topleft, bottomright);\n\n }.bind(this));\n\n }\n\n}\n","import {Framework} from '../framework.js';\n\nimport {Util} from '../util.js';\n\nexport class OpenSeaDragon extends Framework {\n constructor(instance) {\n super(instance);\n this.name = 'opensedragon';\n\n }\n\n get_image(from_canvas) {\n \n\n // TODO needs to be generic and executed with Boostlet.init\n\n let viewer = null;\n let vs = this.instance._viewers;\n vs.forEach(function(e) { \n if (e.id == 'viewer') {\n viewer = e;\n }\n });\n\n if (!viewer) {\n throw \"OpenSeaDragon viewer not found.\";\n }\n\n let canvas = viewer.canvas.children[0];\n let ctx = canvas.getContext(\"2d\");\n\n let image = ctx.getImageData(0, 0, canvas.width, canvas.height);\n let rgba_image = Util.rgba_to_grayscale(image.data);\n let pixels = image.data;\n\n if(from_canvas){\n return {'data':pixels, 'width':image.width, 'height':image.height};\n }\n else{\n return {'data':rgba_image, 'width':image.width, 'height':image.height};\n }\n \n }\n\n set_image(new_pixels) {\n\n let viewer = null;\n let vs = this.instance._viewers;\n vs.forEach(function(e) { \n if (e.id == 'viewer') {\n viewer = e;\n }\n });\n\n if (!viewer) {\n throw \"OpenSeaDragon viewer not found.\";\n }\n\n let canvas = viewer.canvas.children[0];\n let ctx = canvas.getContext(\"2d\");\n let new_image = new ImageData(new Uint8ClampedArray(Util.grayscale_to_rgba(new_pixels)), image.width, image.height);\n\n ctx.putImageData(new_image, 0, 0);\n\n }\n\n set_mask(new_mask) {\n\n let viewer = null;\n let vs = this.instance._viewers;\n vs.forEach(function(e) { \n if (e.id == 'viewer') {\n viewer = e;\n }\n });\n\n if (!viewer) {\n throw \"OpenSeaDragon viewer not found.\";\n }\n\n let canvas = viewer.canvas.children[0];\n width = canvas.width;\n height = canvas.height;\n\n let ctx = canvas.getContext('2d');\n let imagedata = ctx.getImageData(0, 0, width, height);\n let pixels = imagedata.data;\n\n let masked_image = Util.harden_mask(pixels, new_mask);\n\n // console.log(masked_image);\n\n let masked_image_as_imagedata = new ImageData(masked_image, width, height);\n\n // console.log(masked_image_as_imagedata);\n\n ctx.putImageData(masked_image_as_imagedata, 0, 0);\n\n\n }\n\n select_box(callback) {\n\n \n // alert(\"Click on top left and bottom rght coordinated of the desired selection box.\")\n let isFirstClick = true;\n let x1, y1, x2, y2;\n \n // Function to handle the mouse click event\n function handleClick(event) {\n if (isFirstClick) {\n // Capture x1 and y1 on the first click\n x1 = event.clientX;\n y1 = event.clientY;\n console.log(`First click: (X1: ${x1}, Y1: ${y1})`);\n isFirstClick = false;\n } else {\n // Capture x2 and y2 on the second click\n x2 = event.clientX;\n y2 = event.clientY;\n console.log(`Second click: (X2: ${x2}, Y2: ${y2})`);\n isFirstClick = true;\n\n let topleft = {x: x1, y: y1};\n let bottomright = {x: x2, y: y2};\n\n callback(topleft, bottomright);\n }\n\n // let topleft = {x: 529, y: 480};\n // let bottomright = {x: 667, y: 588};\n // callback(topleft, bottomright);\n\n }\n \n \n // Add a click event listener to the document\n document.addEventListener(\"click\", handleClick);\n\n\n }\n\n \n\n}\n \n","\nimport {Boostlet} from \"./boostlet.js\"\n\nwindow.console.log('BOOSTLET VERSION 0.1-beta');\n\n// register global namespace with a new boostlet instance\n// later we might want to support multiple active boostlets\nwindow.Boostlet = new Boostlet();\n","import {Util} from './util.js';\n\nimport {Framework} from './framework.js';\n\nexport class Boostlet {\n\n constructor() {\n\n this.framework = null;\n\n }\n\n /**\n * Initializes the Boostlet.\n * \n * This includes several steps such as identifying the \n * visualization/rendering framework that is available. \n * \n * TODO: Later we want to have fallbacks in place if the framework\n * is not detected.\n * \n */\n init(name, instance) {\n\n if (typeof name != 'undefined' && typeof instance != 'undefined') {\n\n console.log('Framework forced by user!');\n throw \"Forced Framework Not Implemented.\";\n // TODO\n\n } else {\n\n this.framework = Util.detect_framework();\n\n }\n\n if (this.framework) {\n\n console.log('Found', this.framework, '!')\n \n } else {\n\n throw \"Framework Not Found.\";\n\n }\n\n }\n\n /**\n * Let's the user select a region of interest box.\n */\n async select_box(callback) {\n\n this.framework.select_box(callback);\n\n }\n\n /**\n * Let's the user select (multiple) seeds.\n */\n async select_seed(howmany) {\n\n throw \"Missing Implementation.\";\n\n }\n\n /**\n * Loads an external javascript file asynchronously. \n */\n async load_script(url, callback) {\n\n Util.load_script(url, callback);\n\n }\n\n /**\n * Sends a HTTP POST request to a url with some data.\n */\n async send_http_post(url, data, callback) {\n\n Util.send_http_post(url, data, callback);\n\n }\n\n /**\n * Gets the current image (2D).\n * \n * TODO: Optional bounding box should be supported.\n * \n */\n get_image(from_canvas) {\n\n return this.framework.get_image(from_canvas);\n\n }\n\n /**\n * Sets the current image (2D).\n * \n */\n set_image(new_pixels) {\n\n return this.framework.set_image(new_pixels);\n\n }\n\n /**\n * Sets the current mask (2D).\n * \n */\n set_mask(new_mask) {\n\n return this.framework.set_mask(new_mask);\n\n }\n\n /**\n * Encode raw image data to PNG.\n */\n convert_to_png(uint8array, width, height) {\n\n return this.framework.convert_to_png(uint8array, width, height);\n\n }\n\n filter(pixels, width, height, kernel) {\n\n return Util.filter(pixels, width, height, kernel);\n\n }\n\n}\n"],"names":[],"version":3,"file":"boostlet.min.js.map"} \ No newline at end of file +{"mappings":"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","sources":["src/util.js","src/framework.js","src/frameworks/cornerstone2d.js","src/frameworks/niivue.js","src/frameworks/openseadragon.js","src/index.js","src/boostlet.js"],"sourcesContent":["import {Framework} from './framework.js';\nimport {Cornerstone2D} from './frameworks/cornerstone2d.js';\nimport {NiiVue} from './frameworks/niivue.js';\nimport { OpenSeaDragon } from './frameworks/openseadragon.js';\n\nexport class Util {\n \n static detect_framework() {\n\n let framework = null;\n\n if (Util.is_defined(window.nv)) {\n \n framework = new NiiVue(window.nv);\n \n } else if (Util.is_defined(window.niivue)) {\n \n framework = new NiiVue(window.niivue);\n\n } else if (Util.is_defined(window.cornerstone)) {\n\n framework = new Cornerstone2D(window.cornerstone);\n\n } else if (Util.is_defined(window.OpenSeadragon)) {\n\n framework = new OpenSeaDragon(window.OpenSeadragon);\n \n }\n\n // TODO: fallback to general canvas or webgl framework\n\n return framework;\n\n }\n\n static async load_script(url, callback) {\n\n // introducing hack to make it work for openneuro\n window.Object.defineProperty(window.Object.prototype, 'global', {\n get( ){\n return window;\n },\n set(newGlobal) {\n globalThis = newGlobal;\n }\n });\n\n const script = window.document.createElement(\"script\")\n script.type = \"text/javascript\"\n script.src = url;\n\n if (Util.is_defined(callback)) {\n script.onload = callback;\n }\n\n window.document.head.appendChild(script);\n eval(script);\n\n }\n\n static async send_http_post(url, data, callback) {\n\n let xhr = new XMLHttpRequest();\n xhr.open(\"POST\", url);\n xhr.onreadystatechange = function () {\n if (xhr.readyState === 4) {\n // request done\n callback( xhr.response );\n\n return;\n\n }\n }\n\n xhr.send(data)\n\n }\n\n static convert_to_png(uint8array, width, height, flip) {\n\n // we are using an offscreen canvas for this\n let offscreen = window.document.createElement('canvas');\n offscreen.width = width;\n offscreen.height = height;\n\n let offscreen_ctx = offscreen.getContext('2d');\n\n let imgdata = offscreen_ctx.createImageData(offscreen.width, offscreen.height);\n let pxdata = imgdata.data;\n\n for (var i =0; i c.charCodeAt(0));\n\n return pngpixels;\n\n }\n\n static filter(pixels, width, height, kernel) {\n\n const kernelSize = Math.sqrt(kernel.length);\n const halfKernelSize = Math.floor(kernelSize / 2);\n\n const new_pixels = pixels.slice();\n\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const dstIndex = y * width + x;\n\n let newValue = 0;\n for (let ky = 0; ky < kernelSize; ky++) {\n for (let kx = 0; kx < kernelSize; kx++) {\n const srcX = x + kx - halfKernelSize;\n const srcY = y + ky - halfKernelSize;\n const srcIndex = srcY * width + srcX;\n\n const kernelValue = kernel[ky * kernelSize + kx];\n newValue += pixels[srcIndex] * kernelValue;\n }\n }\n\n new_pixels[dstIndex] = newValue;\n\n }\n }\n\n return new_pixels;\n\n }\n\n static grayscale_to_rgba(grayscale) {\n\n const rgba = new Uint8Array(grayscale.length * 4);\n\n for (let i = 0; i < grayscale.length; i++) {\n const g = grayscale[i];\n const index = i * 4;\n\n rgba[index] = g;\n rgba[index + 1] = g;\n rgba[index + 2] = g;\n rgba[index + 3] = 255; \n }\n\n return rgba;\n\n }\n\n static rgba_to_grayscale(rgba) {\n\n const grayscale = new Uint8Array(rgba.length / 4);\n\n for (let i = 0; i < rgba.length; i += 4) {\n\n grayscale[i / 4] = rgba[i];\n\n }\n\n return grayscale;\n\n }\n\n /**\n * Harden a mask into a grayscale pixel array.\n * \n * pixels needs to be RGBA\n * \n * and mask binary.\n * \n * maskcolor is optional and falls back to blue.\n * \n **/\n static harden_mask(pixels, mask, maskcolor) {\n\n // Modified from: https://github.com/facebookresearch/segment-anything/blob/40df6e4046d8b07ab8c4519e083408289eb43032/demo/src/components/helpers/maskUtils.tsx\n // Copyright (c) Meta Platforms, Inc. and affiliates.\n // All rights reserved.\n\n\n let maskcolor_ = [0, 114, 189, 255];\n\n if (Util.is_defined(maskcolor)) {\n \n maskcolor_ = maskcolor;\n \n } \n\n for (var i = 0; i < mask.length; i++) {\n\n if (mask[i] > 0.0) {\n pixels[4 * i + 0] = maskcolor_[0];\n pixels[4 * i + 1] = maskcolor_[1];\n pixels[4 * i + 2] = maskcolor_[2];\n pixels[4 * i + 3] = maskcolor_[3];\n }\n\n }\n\n return pixels;\n\n }\n\n static is_defined(variable) {\n\n return (typeof variable != 'undefined');\n\n }\n\n}","import {Util} from './util.js';\n\nexport class Framework {\n\n constructor(instance) {\n\n this.name = 'generic';\n this.instance = instance;\n\n this.flip_on_png = false;\n\n }\n\n get_image(from_canvas) {\n\n throw \"Missing Implementation.\";\n\n }\n\n set_image(new_pixels) {\n\n throw \"Missing Implementation.\";\n\n }\n\n set_mask(new_mask) {\n\n throw \"Missing Implementation.\";\n \n }\n\n select_box(callback) {\n\n throw \"Missing Implementation.\";\n\n }\n\n convert_to_png(uint8array, width, height) {\n\n return Util.convert_to_png(uint8array, width, height, this.flip_on_png);\n\n }\n\n}\n","import {Framework} from '../framework.js';\n\nimport {Util} from '../util.js';\n\nexport class Cornerstone2D extends Framework {\n \n constructor(instance) {\n\n super(instance);\n this.name = 'cornerstone2D';\n\n this.cornerstonetools_instance = null;\n\n if (typeof window.cornerstoneTools != 'undefined') {\n\n // TODO probably not too robust\n this.cornerstonetools_instance = window.cornerstoneTools;\n\n }\n\n this.flip_on_png = false;\n\n }\n\n get_image(from_canvas) {\n\n let element = this.instance.getEnabledElements()[0];\n let pixels = null;\n let width = null;\n let height = null;\n\n if (typeof from_canvas != 'undefined') {\n\n // TODO this is hacky going through the canvas\n // later should grab the real volume data\n\n let canvas = element.canvas;\n width = canvas.width;\n height = canvas.height;\n\n let ctx = canvas.getContext('2d');\n\n let imagedata = ctx.getImageData(0, 0, width, height);\n pixels = imagedata.data;\n\n } else {\n\n // this is the real image slice data\n let imagedata = element.image;\n pixels = imagedata.getPixelData();\n width = imagedata.width;\n height = imagedata.height;\n\n }\n\n return {'data':pixels, 'width':width, 'height':height};\n\n }\n\n set_image(new_pixels) {\n\n let element = this.instance.getEnabledElements()[0];\n let pixels = element.image.getPixelData();\n\n // Set the new pixel values\n pixels.set(new_pixels);\n\n // Re-render the current slice\n cornerstone.renderGrayscaleImage(element, true);\n\n }\n\n set_mask(new_mask) {\n\n // TODO this needs to use segmentation/labelmap layers\n // from cornerstone\n // right now, this is modifying the canvas\n\n let element = this.instance.getEnabledElements()[0];\n\n let canvas = element.canvas;\n width = canvas.width;\n height = canvas.height;\n\n let ctx = canvas.getContext('2d');\n\n let imagedata = ctx.getImageData(0, 0, width, height);\n let pixels = imagedata.data;\n\n let masked_image = Util.harden_mask(pixels, new_mask);\n\n let masked_image_as_imagedata = new ImageData(masked_image, width, height);\n\n ctx.putImageData(masked_image_as_imagedata, 0, 0);\n \n }\n\n select_box(callback) {\n\n this.cornerstonetools_instance.setToolActive('RectangleRoi', { mouseButtonMask: 1 })\n\n let element = this.instance.getEnabledElements()[0];\n let canvas = element.canvas;\n\n canvas.onmouseup = function() {\n\n let state = this.cornerstonetools_instance.globalImageIdSpecificToolStateManager.saveToolState();\n\n let topleft = state[Object.keys(state).pop()].RectangleRoi.data[0].handles.start;\n let bottomright = state[Object.keys(state).pop()].RectangleRoi.data[0].handles.end;\n\n let topleft_c = this.instance.pixelToCanvas(element.element, topleft);\n let bottomright_c = this.instance.pixelToCanvas(element.element, bottomright);\n\n this.cornerstonetools_instance.clearToolState(element.element, 'RectangleRoi');\n this.instance.renderGrayscaleImage(element, true);\n\n callback(topleft_c, bottomright_c);\n\n }.bind(this);\n\n }\n\n}\n","import {Framework} from '../framework.js';\n\nimport {Util} from '../util.js';\n\nexport class NiiVue extends Framework {\n \n constructor(instance) {\n\n super(instance);\n this.name = 'niivue';\n\n this.flip_on_png = true;\n\n this.onMouseDown = false;\n this.x1 = null;\n this.y1 = null;\n this.x2 = null;\n this.y2 = null;\n\n }\n\n get_image(from_canvas) {\n\n let element = this.instance.canvas;\n let pixels = null;\n let width = null;\n let height = null;\n\n\n // TODO this is hacky going through the canvas\n // later should grab the real volume data\n\n let old_crosshaircolor = this.instance.opts.crosshairColor;\n let old_crosshairwidth = this.instance.opts.crosshairWidth;\n\n this.instance.setCrosshairColor([0,0,0,0]);\n this.instance.opts.crosshairWidth=0;\n this.instance.updateGLVolume();\n\n\n let ctx = this.instance.gl;\n\n \n width = ctx.drawingBufferWidth;\n height = ctx.drawingBufferHeight;\n\n pixels = new Uint8Array(width * height * 4);\n ctx.readPixels(\n 0, \n 0, \n width, \n height, \n ctx.RGBA, \n ctx.UNSIGNED_BYTE, \n pixels);\n\n // restore crosshairs\n this.instance.setCrosshairColor(old_crosshaircolor);\n this.instance.opts.crosshairWidth = old_crosshairwidth;\n\n if (!Util.is_defined(from_canvas)) {\n\n // convert rgba pixels to grayscale\n pixels = Util.rgba_to_grayscale(pixels);\n\n } else {\n\n // TODO\n // not easily possible yet\n // we could hack it using \n // nv.back.get_value(x,y,z)\n // based on the dimensions\n // nv.back.dims.slice(1);\n // but devs promised easy access in the future\n\n }\n\n\n return {'data':pixels, 'width':width, 'height':height};\n\n }\n\n /**\n * Sets the NiiVue.js image.\n * \n * If is_rgba==true, we do *not* convert to RGBA before setting on canvas.\n **/\n set_image(new_pixels, is_rgba, no_flip) {\n\n // TODO this is hacky since we dont work with the real volume yet\n // create new canvas\n // put pixels on canvas\n // show canvas\n // hide on click\n\n let originalcanvas = this.instance.canvas;\n\n let newcanvas = window.document.createElement('canvas');\n newcanvas.width = originalcanvas.width;\n newcanvas.height = originalcanvas.height;\n\n // put new_pixels down\n let ctx = newcanvas.getContext('2d');\n\n let new_pixels_rgba = null;\n\n if (Util.is_defined(is_rgba)) {\n\n new_pixels_rgba = new_pixels;\n\n } else {\n\n new_pixels_rgba = Util.grayscale_to_rgba(new_pixels);\n\n\n }\n\n let new_pixels_clamped = new Uint8ClampedArray(new_pixels_rgba);\n\n let new_image_data = new ImageData(new_pixels_clamped, newcanvas.width, newcanvas.height);\n \n\n ctx.putImageData(new_image_data, 0, 0);\n\n if (!Util.is_defined(no_flip)) {\n // some flipping action\n ctx.save();\n ctx.scale(1, -1);\n ctx.drawImage(newcanvas, 0, -newcanvas.height);\n ctx.restore();\n }\n\n\n newcanvas.onclick = function() {\n\n // on click, we will restore the nv canvas\n newcanvas.parentNode.replaceChild(originalcanvas, newcanvas);\n\n }\n\n // replace nv canvas with new one\n originalcanvas.parentNode.replaceChild(newcanvas, originalcanvas);\n newcanvas.style.width = originalcanvas.clientWidth+'px';\n newcanvas.style.height = originalcanvas.clientHeight+'px';\n\n }\n\n set_mask(new_mask) {\n\n // merge image + mask\n // and then call set_image with that information\n\n let image = this.get_image(true);\n\n // TODO here we need to flip one more time, this is until\n // we use the official niivue infrastructure for adding\n // a segmentation layer\n let originalcanvas = this.instance.canvas;\n\n let newcanvas = window.document.createElement('canvas');\n newcanvas.width = originalcanvas.width;\n newcanvas.height = originalcanvas.height;\n // put new_pixels down\n let ctx = newcanvas.getContext('2d');\n let imageclamped = new Uint8ClampedArray(image.data);\n let imagedata = new ImageData(imageclamped, image.width, image.height);\n ctx.putImageData(imagedata, 0, 0);\n ctx.save();\n ctx.scale(1, -1);\n ctx.drawImage(newcanvas, 0, -newcanvas.height);\n ctx.restore();\n image = ctx.getImageData(0, 0, newcanvas.width, newcanvas.height);\n // end of flip\n\n let masked_image = Util.harden_mask(image.data, new_mask);\n\n this.set_image(masked_image, true, true); // rgba data, no flip\n\n\n }\n\n select_box(callback) {\n\n // TODO also hacky until official API supports this\n\n let canvas = this.instance.canvas;\n\n\n canvas.addEventListener('mousedown', function (e) {\n this.isMouseDown = true;\n\n var rect = e.currentTarget.getBoundingClientRect(),\n offsetX = e.clientX - rect.left,\n offsetY = e.clientY - rect.top;\n\n this.x1 = offsetX;\n this.y1 = offsetY;\n }.bind(this));\n\n canvas.addEventListener('mousemove', function (e) {\n if (this.isMouseDown) {\n\n var rect = e.currentTarget.getBoundingClientRect(),\n offsetX = e.clientX - rect.left,\n offsetY = e.clientY - rect.top;\n\n this.x2 = offsetX;\n this.y2 = offsetY;\n this.instance.drawSelectionBox([this.x1, this.y1, this.x2-this.x1, this.y2-this.y1]);\n }\n }.bind(this));\n\n\n canvas.addEventListener('mouseup', function (e) {\n var rect = e.currentTarget.getBoundingClientRect(),\n offsetX = e.clientX - rect.left,\n offsetY = e.clientY - rect.top;\n \n this.x2 = offsetX;\n this.y2 = offsetY;\n this.isMouseDown = false;\n\n let topleft = {x: this.x1, y: this.y1};\n let bottomright = {x: this.x2, y: this.y2};\n\n callback(topleft, bottomright);\n\n }.bind(this));\n\n }\n\n}\n","import {Framework} from '../framework.js';\n\nimport {Util} from '../util.js';\n\nexport class OpenSeaDragon extends Framework {\n constructor(instance) {\n super(instance);\n this.name = 'opensedragon';\n\n }\n\n get_image(from_canvas) {\n \n\n // TODO needs to be generic and executed with Boostlet.init\n\n let viewer = null;\n let vs = this.instance._viewers;\n vs.forEach(function(e) { \n if (e.id == 'viewer') {\n viewer = e;\n }\n });\n\n if (!viewer) {\n throw \"OpenSeaDragon viewer not found.\";\n }\n\n let canvas = viewer.canvas.children[0];\n let ctx = canvas.getContext(\"2d\");\n\n let image = ctx.getImageData(0, 0, canvas.width, canvas.height);\n let rgba_image = Util.rgba_to_grayscale(image.data);\n let pixels = image.data;\n\n if(from_canvas){\n return {'data':pixels, 'width':image.width, 'height':image.height};\n }\n else{\n return {'data':rgba_image, 'width':image.width, 'height':image.height};\n }\n \n }\n\n set_image(new_pixels) {\n\n let viewer = null;\n let vs = this.instance._viewers;\n vs.forEach(function(e) { \n if (e.id == 'viewer') {\n viewer = e;\n }\n });\n\n if (!viewer) {\n throw \"OpenSeaDragon viewer not found.\";\n }\n\n let canvas = viewer.canvas.children[0];\n let ctx = canvas.getContext(\"2d\");\n let new_image = new ImageData(new Uint8ClampedArray(Util.grayscale_to_rgba(new_pixels)), image.width, image.height);\n\n ctx.putImageData(new_image, 0, 0);\n\n }\n\n set_mask(new_mask) {\n\n let viewer = null;\n let vs = this.instance._viewers;\n vs.forEach(function(e) { \n if (e.id == 'viewer') {\n viewer = e;\n }\n });\n\n if (!viewer) {\n throw \"OpenSeaDragon viewer not found.\";\n }\n\n let canvas = viewer.canvas.children[0];\n width = canvas.width;\n height = canvas.height;\n\n let ctx = canvas.getContext('2d');\n let imagedata = ctx.getImageData(0, 0, width, height);\n let pixels = imagedata.data;\n\n let masked_image = Util.harden_mask(pixels, new_mask);\n\n // console.log(masked_image);\n\n let masked_image_as_imagedata = new ImageData(masked_image, width, height);\n\n // console.log(masked_image_as_imagedata);\n\n ctx.putImageData(masked_image_as_imagedata, 0, 0);\n\n\n }\n\n select_box(callback) {\n\n \n // alert(\"Click on top left and bottom rght coordinated of the desired selection box.\")\n let isFirstClick = true;\n let x1, y1, x2, y2;\n \n // Function to handle the mouse click event\n function handleClick(event) {\n if (isFirstClick) {\n // Capture x1 and y1 on the first click\n x1 = event.clientX;\n y1 = event.clientY;\n console.log(`First click: (X1: ${x1}, Y1: ${y1})`);\n isFirstClick = false;\n } else {\n // Capture x2 and y2 on the second click\n x2 = event.clientX;\n y2 = event.clientY;\n console.log(`Second click: (X2: ${x2}, Y2: ${y2})`);\n isFirstClick = true;\n\n let topleft = {x: x1, y: y1};\n let bottomright = {x: x2, y: y2};\n\n callback(topleft, bottomright);\n }\n\n // let topleft = {x: 529, y: 480};\n // let bottomright = {x: 667, y: 588};\n // callback(topleft, bottomright);\n\n }\n \n \n // Add a click event listener to the document\n document.addEventListener(\"click\", handleClick);\n\n\n }\n\n \n\n}\n \n","\nimport {Boostlet} from \"./boostlet.js\"\n\nwindow.console.log('BOOSTLET VERSION 0.1-beta');\n\n// register global namespace with a new boostlet instance\n// later we might want to support multiple active boostlets\nwindow.Boostlet = new Boostlet();\n","import {Util} from './util.js';\n\nimport {Framework} from './framework.js';\n\nexport class Boostlet {\n\n constructor() {\n\n this.framework = null;\n\n }\n\n /**\n * Initializes the Boostlet.\n * \n * This includes several steps such as identifying the \n * visualization/rendering framework that is available. \n * \n * TODO: Later we want to have fallbacks in place if the framework\n * is not detected.\n * \n */\n init(name, instance) {\n\n if (typeof name != 'undefined' && typeof instance != 'undefined') {\n\n console.log('Framework forced by user!');\n throw \"Forced Framework Not Implemented.\";\n // TODO\n\n } else {\n\n this.framework = Util.detect_framework();\n\n }\n\n if (this.framework) {\n\n console.log('Found', this.framework, '!')\n \n } else {\n\n throw \"Framework Not Found.\";\n\n }\n\n }\n\n /**\n * Let's the user select a region of interest box.\n */\n async select_box(callback) {\n\n this.framework.select_box(callback);\n\n }\n\n /**\n * Let's the user select (multiple) seeds.\n */\n async select_seed(howmany) {\n\n throw \"Missing Implementation.\";\n\n }\n\n /**\n * Loads an external javascript file asynchronously. \n */\n async load_script(url, callback) {\n\n Util.load_script(url, callback);\n\n }\n\n /**\n * Sends a HTTP POST request to a url with some data.\n */\n async send_http_post(url, data, callback) {\n\n Util.send_http_post(url, data, callback);\n\n }\n\n /**\n * Gets the current image (2D).\n * \n * TODO: Optional bounding box should be supported.\n * \n */\n get_image(from_canvas) {\n\n return this.framework.get_image(from_canvas);\n\n }\n\n /**\n * Sets the current image (2D).\n * \n */\n set_image(new_pixels) {\n\n return this.framework.set_image(new_pixels);\n\n }\n\n /**\n * Sets the current mask (2D).\n * \n */\n set_mask(new_mask) {\n\n return this.framework.set_mask(new_mask);\n\n }\n\n /**\n * Encode raw image data to PNG.\n */\n convert_to_png(uint8array, width, height) {\n\n return this.framework.convert_to_png(uint8array, width, height);\n\n }\n\n filter(pixels, width, height, kernel) {\n\n return Util.filter(pixels, width, height, kernel);\n\n }\n\n}\n"],"names":[],"version":3,"file":"boostlet.min.js.map"} \ No newline at end of file diff --git a/src/frameworks/niivue.js b/src/frameworks/niivue.js index e446c485..d13ad43e 100644 --- a/src/frameworks/niivue.js +++ b/src/frameworks/niivue.js @@ -140,8 +140,8 @@ export class NiiVue extends Framework { // replace nv canvas with new one originalcanvas.parentNode.replaceChild(newcanvas, originalcanvas); - newcanvas.style.width = originalcanvas.clientWidth; - newcanvas.style.height = originalcanvas.clientHeight; + newcanvas.style.width = originalcanvas.clientWidth+'px'; + newcanvas.style.height = originalcanvas.clientHeight+'px'; }