Update pica to 5.1.0
authorTim Düsterhus <duesterhus@woltlab.com>
Sat, 16 May 2020 11:23:48 +0000 (13:23 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Mon, 22 Jun 2020 09:40:41 +0000 (11:40 +0200)
wcfsetup/install/files/js/3rdParty/pica.js

index 08c620e46eed51b578e1dd1764a5dc09a5b0ab15..d1c5e545c5436d97e5bfc829bd8534002283fccd 100644 (file)
@@ -1,79 +1,58 @@
-/* (The MIT License)
-
-Copyright (C) 2014-2017 by Vitaly Puzrin
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE. */
-/* pica 5.0.0 nodeca/pica */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.pica = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
+/* pica 5.1.0 nodeca/pica */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.pica = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
 // Collection of math functions
 //
 // 1. Combine components together
 // 2. Has async init to load wasm modules
 //
-               'use strict';
-               
-               var inherits = require('inherits');
-               
-               var Multimath = require('multimath');
-               
-               var mm_unsharp_mask = require('multimath/lib/unsharp_mask');
-               
-               var mm_resize = require('./mm_resize');
-               
-               function MathLib(requested_features) {
-                       var __requested_features = requested_features || [];
-                       
-                       var features = {
-                               js: __requested_features.indexOf('js') >= 0,
-                               wasm: __requested_features.indexOf('wasm') >= 0
-                       };
-                       Multimath.call(this, features);
-                       this.features = {
-                               js: features.js,
-                               wasm: features.wasm && this.has_wasm
-                       };
-                       this.use(mm_unsharp_mask);
-                       this.use(mm_resize);
-               }
-               
-               inherits(MathLib, Multimath);
-               
-               MathLib.prototype.resizeAndUnsharp = function resizeAndUnsharp(options, cache) {
-                       var result = this.resize(options, cache);
-                       
-                       if (options.unsharpAmount) {
-                               this.unsharp_mask(result, options.toWidth, options.toHeight, options.unsharpAmount, options.unsharpRadius, options.unsharpThreshold);
-                       }
-                       
-                       return result;
-               };
-               
-               module.exports = MathLib;
-               
-       },{"./mm_resize":4,"inherits":15,"multimath":16,"multimath/lib/unsharp_mask":19}],2:[function(require,module,exports){
+'use strict';
+
+var inherits = require('inherits');
+
+var Multimath = require('multimath');
+
+var mm_unsharp_mask = require('multimath/lib/unsharp_mask');
+
+var mm_resize = require('./mm_resize');
+
+function MathLib(requested_features) {
+  var __requested_features = requested_features || [];
+
+  var features = {
+    js: __requested_features.indexOf('js') >= 0,
+    wasm: __requested_features.indexOf('wasm') >= 0
+  };
+  Multimath.call(this, features);
+  this.features = {
+    js: features.js,
+    wasm: features.wasm && this.has_wasm()
+  };
+  this.use(mm_unsharp_mask);
+  this.use(mm_resize);
+}
+
+inherits(MathLib, Multimath);
+
+MathLib.prototype.resizeAndUnsharp = function resizeAndUnsharp(options, cache) {
+  var result = this.resize(options, cache);
+
+  if (options.unsharpAmount) {
+    this.unsharp_mask(result, options.toWidth, options.toHeight, options.unsharpAmount, options.unsharpRadius, options.unsharpThreshold);
+  }
+
+  return result;
+};
+
+module.exports = MathLib;
+
+},{"./mm_resize":4,"inherits":15,"multimath":16,"multimath/lib/unsharp_mask":19}],2:[function(require,module,exports){
 // Resize convolvers, pure JS implementation
 //
-               'use strict'; // Precision of fixed FP values
+'use strict'; // Precision of fixed FP values
 //var FIXED_FRAC_BITS = 14;
-               
-               function clampTo8(i) {
-                       return i < 0 ? 0 : i > 255 ? 255 : i;
-               } // Convolve image in horizontal directions and transpose output. In theory,
+
+function clampTo8(i) {
+  return i < 0 ? 0 : i > 255 ? 255 : i;
+} // Convolve image in horizontal directions and transpose output. In theory,
 // transpose allow:
 //
 // - use the same convolver for both passes (this fails due different
@@ -82,192 +61,192 @@ THE SOFTWARE. */
 //
 // But in real life this doesn't work :)
 //
-               
-               
-               function convolveHorizontally(src, dest, srcW, srcH, destW, filters) {
-                       var r, g, b, a;
-                       var filterPtr, filterShift, filterSize;
-                       var srcPtr, srcY, destX, filterVal;
-                       var srcOffset = 0,
-                               destOffset = 0; // For each row
-                       
-                       for (srcY = 0; srcY < srcH; srcY++) {
-                               filterPtr = 0; // Apply precomputed filters to each destination row point
-                               
-                               for (destX = 0; destX < destW; destX++) {
-                                       // Get the filter that determines the current output pixel.
-                                       filterShift = filters[filterPtr++];
-                                       filterSize = filters[filterPtr++];
-                                       srcPtr = srcOffset + filterShift * 4 | 0;
-                                       r = g = b = a = 0; // Apply the filter to the row to get the destination pixel r, g, b, a
-                                       
-                                       for (; filterSize > 0; filterSize--) {
-                                               filterVal = filters[filterPtr++]; // Use reverse order to workaround deopts in old v8 (node v.10)
-                                               // Big thanks to @mraleph (Vyacheslav Egorov) for the tip.
-                                               
-                                               a = a + filterVal * src[srcPtr + 3] | 0;
-                                               b = b + filterVal * src[srcPtr + 2] | 0;
-                                               g = g + filterVal * src[srcPtr + 1] | 0;
-                                               r = r + filterVal * src[srcPtr] | 0;
-                                               srcPtr = srcPtr + 4 | 0;
-                                       } // Bring this value back in range. All of the filter scaling factors
-                                       // are in fixed point with FIXED_FRAC_BITS bits of fractional part.
-                                       //
-                                       // (!) Add 1/2 of value before clamping to get proper rounding. In other
-                                       // case brightness loss will be noticeable if you resize image with white
-                                       // border and place it on white background.
-                                       //
-                                       
-                                       
-                                       dest[destOffset + 3] = clampTo8(a + (1 << 13) >> 14
-                                               /*FIXED_FRAC_BITS*/
-                                       );
-                                       dest[destOffset + 2] = clampTo8(b + (1 << 13) >> 14
-                                               /*FIXED_FRAC_BITS*/
-                                       );
-                                       dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14
-                                               /*FIXED_FRAC_BITS*/
-                                       );
-                                       dest[destOffset] = clampTo8(r + (1 << 13) >> 14
-                                               /*FIXED_FRAC_BITS*/
-                                       );
-                                       destOffset = destOffset + srcH * 4 | 0;
-                               }
-                               
-                               destOffset = (srcY + 1) * 4 | 0;
-                               srcOffset = (srcY + 1) * srcW * 4 | 0;
-                       }
-               } // Technically, convolvers are the same. But input array and temporary
+
+
+function convolveHorizontally(src, dest, srcW, srcH, destW, filters) {
+  var r, g, b, a;
+  var filterPtr, filterShift, filterSize;
+  var srcPtr, srcY, destX, filterVal;
+  var srcOffset = 0,
+      destOffset = 0; // For each row
+
+  for (srcY = 0; srcY < srcH; srcY++) {
+    filterPtr = 0; // Apply precomputed filters to each destination row point
+
+    for (destX = 0; destX < destW; destX++) {
+      // Get the filter that determines the current output pixel.
+      filterShift = filters[filterPtr++];
+      filterSize = filters[filterPtr++];
+      srcPtr = srcOffset + filterShift * 4 | 0;
+      r = g = b = a = 0; // Apply the filter to the row to get the destination pixel r, g, b, a
+
+      for (; filterSize > 0; filterSize--) {
+        filterVal = filters[filterPtr++]; // Use reverse order to workaround deopts in old v8 (node v.10)
+        // Big thanks to @mraleph (Vyacheslav Egorov) for the tip.
+
+        a = a + filterVal * src[srcPtr + 3] | 0;
+        b = b + filterVal * src[srcPtr + 2] | 0;
+        g = g + filterVal * src[srcPtr + 1] | 0;
+        r = r + filterVal * src[srcPtr] | 0;
+        srcPtr = srcPtr + 4 | 0;
+      } // Bring this value back in range. All of the filter scaling factors
+      // are in fixed point with FIXED_FRAC_BITS bits of fractional part.
+      //
+      // (!) Add 1/2 of value before clamping to get proper rounding. In other
+      // case brightness loss will be noticeable if you resize image with white
+      // border and place it on white background.
+      //
+
+
+      dest[destOffset + 3] = clampTo8(a + (1 << 13) >> 14
+      /*FIXED_FRAC_BITS*/
+      );
+      dest[destOffset + 2] = clampTo8(b + (1 << 13) >> 14
+      /*FIXED_FRAC_BITS*/
+      );
+      dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14
+      /*FIXED_FRAC_BITS*/
+      );
+      dest[destOffset] = clampTo8(r + (1 << 13) >> 14
+      /*FIXED_FRAC_BITS*/
+      );
+      destOffset = destOffset + srcH * 4 | 0;
+    }
+
+    destOffset = (srcY + 1) * 4 | 0;
+    srcOffset = (srcY + 1) * srcW * 4 | 0;
+  }
+} // Technically, convolvers are the same. But input array and temporary
 // buffer can be of different type (especially, in old browsers). So,
 // keep code in separate functions to avoid deoptimizations & speed loss.
-               
-               
-               function convolveVertically(src, dest, srcW, srcH, destW, filters) {
-                       var r, g, b, a;
-                       var filterPtr, filterShift, filterSize;
-                       var srcPtr, srcY, destX, filterVal;
-                       var srcOffset = 0,
-                               destOffset = 0; // For each row
-                       
-                       for (srcY = 0; srcY < srcH; srcY++) {
-                               filterPtr = 0; // Apply precomputed filters to each destination row point
-                               
-                               for (destX = 0; destX < destW; destX++) {
-                                       // Get the filter that determines the current output pixel.
-                                       filterShift = filters[filterPtr++];
-                                       filterSize = filters[filterPtr++];
-                                       srcPtr = srcOffset + filterShift * 4 | 0;
-                                       r = g = b = a = 0; // Apply the filter to the row to get the destination pixel r, g, b, a
-                                       
-                                       for (; filterSize > 0; filterSize--) {
-                                               filterVal = filters[filterPtr++]; // Use reverse order to workaround deopts in old v8 (node v.10)
-                                               // Big thanks to @mraleph (Vyacheslav Egorov) for the tip.
-                                               
-                                               a = a + filterVal * src[srcPtr + 3] | 0;
-                                               b = b + filterVal * src[srcPtr + 2] | 0;
-                                               g = g + filterVal * src[srcPtr + 1] | 0;
-                                               r = r + filterVal * src[srcPtr] | 0;
-                                               srcPtr = srcPtr + 4 | 0;
-                                       } // Bring this value back in range. All of the filter scaling factors
-                                       // are in fixed point with FIXED_FRAC_BITS bits of fractional part.
-                                       //
-                                       // (!) Add 1/2 of value before clamping to get proper rounding. In other
-                                       // case brightness loss will be noticeable if you resize image with white
-                                       // border and place it on white background.
-                                       //
-                                       
-                                       
-                                       dest[destOffset + 3] = clampTo8(a + (1 << 13) >> 14
-                                               /*FIXED_FRAC_BITS*/
-                                       );
-                                       dest[destOffset + 2] = clampTo8(b + (1 << 13) >> 14
-                                               /*FIXED_FRAC_BITS*/
-                                       );
-                                       dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14
-                                               /*FIXED_FRAC_BITS*/
-                                       );
-                                       dest[destOffset] = clampTo8(r + (1 << 13) >> 14
-                                               /*FIXED_FRAC_BITS*/
-                                       );
-                                       destOffset = destOffset + srcH * 4 | 0;
-                               }
-                               
-                               destOffset = (srcY + 1) * 4 | 0;
-                               srcOffset = (srcY + 1) * srcW * 4 | 0;
-                       }
-               }
-               
-               module.exports = {
-                       convolveHorizontally: convolveHorizontally,
-                       convolveVertically: convolveVertically
-               };
-               
-       },{}],3:[function(require,module,exports){
+
+
+function convolveVertically(src, dest, srcW, srcH, destW, filters) {
+  var r, g, b, a;
+  var filterPtr, filterShift, filterSize;
+  var srcPtr, srcY, destX, filterVal;
+  var srcOffset = 0,
+      destOffset = 0; // For each row
+
+  for (srcY = 0; srcY < srcH; srcY++) {
+    filterPtr = 0; // Apply precomputed filters to each destination row point
+
+    for (destX = 0; destX < destW; destX++) {
+      // Get the filter that determines the current output pixel.
+      filterShift = filters[filterPtr++];
+      filterSize = filters[filterPtr++];
+      srcPtr = srcOffset + filterShift * 4 | 0;
+      r = g = b = a = 0; // Apply the filter to the row to get the destination pixel r, g, b, a
+
+      for (; filterSize > 0; filterSize--) {
+        filterVal = filters[filterPtr++]; // Use reverse order to workaround deopts in old v8 (node v.10)
+        // Big thanks to @mraleph (Vyacheslav Egorov) for the tip.
+
+        a = a + filterVal * src[srcPtr + 3] | 0;
+        b = b + filterVal * src[srcPtr + 2] | 0;
+        g = g + filterVal * src[srcPtr + 1] | 0;
+        r = r + filterVal * src[srcPtr] | 0;
+        srcPtr = srcPtr + 4 | 0;
+      } // Bring this value back in range. All of the filter scaling factors
+      // are in fixed point with FIXED_FRAC_BITS bits of fractional part.
+      //
+      // (!) Add 1/2 of value before clamping to get proper rounding. In other
+      // case brightness loss will be noticeable if you resize image with white
+      // border and place it on white background.
+      //
+
+
+      dest[destOffset + 3] = clampTo8(a + (1 << 13) >> 14
+      /*FIXED_FRAC_BITS*/
+      );
+      dest[destOffset + 2] = clampTo8(b + (1 << 13) >> 14
+      /*FIXED_FRAC_BITS*/
+      );
+      dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14
+      /*FIXED_FRAC_BITS*/
+      );
+      dest[destOffset] = clampTo8(r + (1 << 13) >> 14
+      /*FIXED_FRAC_BITS*/
+      );
+      destOffset = destOffset + srcH * 4 | 0;
+    }
+
+    destOffset = (srcY + 1) * 4 | 0;
+    srcOffset = (srcY + 1) * srcW * 4 | 0;
+  }
+}
+
+module.exports = {
+  convolveHorizontally: convolveHorizontally,
+  convolveVertically: convolveVertically
+};
+
+},{}],3:[function(require,module,exports){
 // This is autogenerated file from math.wasm, don't edit.
 //
-               'use strict';
-               /* eslint-disable max-len */
-               
-               module.exports = 'AGFzbQEAAAABFAJgBn9/f39/fwBgB39/f39/f38AAg8BA2VudgZtZW1vcnkCAAEDAwIAAQQEAXAAAAcZAghjb252b2x2ZQAACmNvbnZvbHZlSFYAAQkBAArmAwLBAwEQfwJAIANFDQAgBEUNACAFQQRqIRVBACEMQQAhDQNAIA0hDkEAIRFBACEHA0AgB0ECaiESAn8gBSAHQQF0IgdqIgZBAmouAQAiEwRAQQAhCEEAIBNrIRQgFSAHaiEPIAAgDCAGLgEAakECdGohEEEAIQlBACEKQQAhCwNAIBAoAgAiB0EYdiAPLgEAIgZsIAtqIQsgB0H/AXEgBmwgCGohCCAHQRB2Qf8BcSAGbCAKaiEKIAdBCHZB/wFxIAZsIAlqIQkgD0ECaiEPIBBBBGohECAUQQFqIhQNAAsgEiATagwBC0EAIQtBACEKQQAhCUEAIQggEgshByABIA5BAnRqIApBgMAAakEOdSIGQf8BIAZB/wFIG0EQdEGAgPwHcUEAIAZBAEobIAtBgMAAakEOdSIGQf8BIAZB/wFIG0EYdEEAIAZBAEobciAJQYDAAGpBDnUiBkH/ASAGQf8BSBtBCHRBgP4DcUEAIAZBAEobciAIQYDAAGpBDnUiBkH/ASAGQf8BSBtB/wFxQQAgBkEAShtyNgIAIA4gA2ohDiARQQFqIhEgBEcNAAsgDCACaiEMIA1BAWoiDSADRw0ACwsLIQACQEEAIAIgAyAEIAUgABAAIAJBACAEIAUgBiABEAALCw==';
-               
-       },{}],4:[function(require,module,exports){
-               'use strict';
-               
-               module.exports = {
-                       name: 'resize',
-                       fn: require('./resize'),
-                       wasm_fn: require('./resize_wasm'),
-                       wasm_src: require('./convolve_wasm_base64')
-               };
-               
-       },{"./convolve_wasm_base64":3,"./resize":5,"./resize_wasm":8}],5:[function(require,module,exports){
-               'use strict';
-               
-               var createFilters = require('./resize_filter_gen');
-               
-               var convolveHorizontally = require('./convolve').convolveHorizontally;
-               
-               var convolveVertically = require('./convolve').convolveVertically;
-               
-               function resetAlpha(dst, width, height) {
-                       var ptr = 3,
-                               len = width * height * 4 | 0;
-                       
-                       while (ptr < len) {
-                               dst[ptr] = 0xFF;
-                               ptr = ptr + 4 | 0;
-                       }
-               }
-               
-               module.exports = function resize(options) {
-                       var src = options.src;
-                       var srcW = options.width;
-                       var srcH = options.height;
-                       var destW = options.toWidth;
-                       var destH = options.toHeight;
-                       var scaleX = options.scaleX || options.toWidth / options.width;
-                       var scaleY = options.scaleY || options.toHeight / options.height;
-                       var offsetX = options.offsetX || 0;
-                       var offsetY = options.offsetY || 0;
-                       var dest = options.dest || new Uint8Array(destW * destH * 4);
-                       var quality = typeof options.quality === 'undefined' ? 3 : options.quality;
-                       var alpha = options.alpha || false;
-                       var filtersX = createFilters(quality, srcW, destW, scaleX, offsetX),
-                               filtersY = createFilters(quality, srcH, destH, scaleY, offsetY);
-                       var tmp = new Uint8Array(destW * srcH * 4); // To use single function we need src & tmp of the same type.
-                       // But src can be CanvasPixelArray, and tmp - Uint8Array. So, keep
-                       // vertical and horizontal passes separately to avoid deoptimization.
-                       
-                       convolveHorizontally(src, tmp, srcW, srcH, destW, filtersX);
-                       convolveVertically(tmp, dest, srcH, destW, destH, filtersY); // That's faster than doing checks in convolver.
-                       // !!! Note, canvas data is not premultipled. We don't need other
-                       // alpha corrections.
-                       
-                       if (!alpha) resetAlpha(dest, destW, destH);
-                       return dest;
-               };
-               
-       },{"./convolve":2,"./resize_filter_gen":6}],6:[function(require,module,exports){
+'use strict';
+/* eslint-disable max-len */
+
+module.exports = 'AGFzbQEAAAABFAJgBn9/f39/fwBgB39/f39/f38AAg8BA2VudgZtZW1vcnkCAAEDAwIAAQQEAXAAAAcZAghjb252b2x2ZQAACmNvbnZvbHZlSFYAAQkBAArmAwLBAwEQfwJAIANFDQAgBEUNACAFQQRqIRVBACEMQQAhDQNAIA0hDkEAIRFBACEHA0AgB0ECaiESAn8gBSAHQQF0IgdqIgZBAmouAQAiEwRAQQAhCEEAIBNrIRQgFSAHaiEPIAAgDCAGLgEAakECdGohEEEAIQlBACEKQQAhCwNAIBAoAgAiB0EYdiAPLgEAIgZsIAtqIQsgB0H/AXEgBmwgCGohCCAHQRB2Qf8BcSAGbCAKaiEKIAdBCHZB/wFxIAZsIAlqIQkgD0ECaiEPIBBBBGohECAUQQFqIhQNAAsgEiATagwBC0EAIQtBACEKQQAhCUEAIQggEgshByABIA5BAnRqIApBgMAAakEOdSIGQf8BIAZB/wFIG0EQdEGAgPwHcUEAIAZBAEobIAtBgMAAakEOdSIGQf8BIAZB/wFIG0EYdEEAIAZBAEobciAJQYDAAGpBDnUiBkH/ASAGQf8BSBtBCHRBgP4DcUEAIAZBAEobciAIQYDAAGpBDnUiBkH/ASAGQf8BSBtB/wFxQQAgBkEAShtyNgIAIA4gA2ohDiARQQFqIhEgBEcNAAsgDCACaiEMIA1BAWoiDSADRw0ACwsLIQACQEEAIAIgAyAEIAUgABAAIAJBACAEIAUgBiABEAALCw==';
+
+},{}],4:[function(require,module,exports){
+'use strict';
+
+module.exports = {
+  name: 'resize',
+  fn: require('./resize'),
+  wasm_fn: require('./resize_wasm'),
+  wasm_src: require('./convolve_wasm_base64')
+};
+
+},{"./convolve_wasm_base64":3,"./resize":5,"./resize_wasm":8}],5:[function(require,module,exports){
+'use strict';
+
+var createFilters = require('./resize_filter_gen');
+
+var convolveHorizontally = require('./convolve').convolveHorizontally;
+
+var convolveVertically = require('./convolve').convolveVertically;
+
+function resetAlpha(dst, width, height) {
+  var ptr = 3,
+      len = width * height * 4 | 0;
+
+  while (ptr < len) {
+    dst[ptr] = 0xFF;
+    ptr = ptr + 4 | 0;
+  }
+}
+
+module.exports = function resize(options) {
+  var src = options.src;
+  var srcW = options.width;
+  var srcH = options.height;
+  var destW = options.toWidth;
+  var destH = options.toHeight;
+  var scaleX = options.scaleX || options.toWidth / options.width;
+  var scaleY = options.scaleY || options.toHeight / options.height;
+  var offsetX = options.offsetX || 0;
+  var offsetY = options.offsetY || 0;
+  var dest = options.dest || new Uint8Array(destW * destH * 4);
+  var quality = typeof options.quality === 'undefined' ? 3 : options.quality;
+  var alpha = options.alpha || false;
+  var filtersX = createFilters(quality, srcW, destW, scaleX, offsetX),
+      filtersY = createFilters(quality, srcH, destH, scaleY, offsetY);
+  var tmp = new Uint8Array(destW * srcH * 4); // To use single function we need src & tmp of the same type.
+  // But src can be CanvasPixelArray, and tmp - Uint8Array. So, keep
+  // vertical and horizontal passes separately to avoid deoptimization.
+
+  convolveHorizontally(src, tmp, srcW, srcH, destW, filtersX);
+  convolveVertically(tmp, dest, srcH, destW, destH, filtersY); // That's faster than doing checks in convolver.
+  // !!! Note, canvas data is not premultipled. We don't need other
+  // alpha corrections.
+
+  if (!alpha) resetAlpha(dest, destW, destH);
+  return dest;
+};
+
+},{"./convolve":2,"./resize_filter_gen":6}],6:[function(require,module,exports){
 // Calculate convolution filters for each destination point,
 // and pack data to Int16Array:
 //
@@ -277,335 +256,335 @@ THE SOFTWARE. */
 // - length - filter length (in src points)
 // - data - filter values sequence
 //
-               'use strict';
-               
-               var FILTER_INFO = require('./resize_filter_info'); // Precision of fixed FP values
-               
-               
-               var FIXED_FRAC_BITS = 14;
-               
-               function toFixedPoint(num) {
-                       return Math.round(num * ((1 << FIXED_FRAC_BITS) - 1));
-               }
-               
-               module.exports = function resizeFilterGen(quality, srcSize, destSize, scale, offset) {
-                       var filterFunction = FILTER_INFO[quality].filter;
-                       var scaleInverted = 1.0 / scale;
-                       var scaleClamped = Math.min(1.0, scale); // For upscale
-                       // Filter window (averaging interval), scaled to src image
-                       
-                       var srcWindow = FILTER_INFO[quality].win / scaleClamped;
-                       var destPixel, srcPixel, srcFirst, srcLast, filterElementSize, floatFilter, fxpFilter, total, pxl, idx, floatVal, filterTotal, filterVal;
-                       var leftNotEmpty, rightNotEmpty, filterShift, filterSize;
-                       var maxFilterElementSize = Math.floor((srcWindow + 1) * 2);
-                       var packedFilter = new Int16Array((maxFilterElementSize + 2) * destSize);
-                       var packedFilterPtr = 0;
-                       var slowCopy = !packedFilter.subarray || !packedFilter.set; // For each destination pixel calculate source range and built filter values
-                       
-                       for (destPixel = 0; destPixel < destSize; destPixel++) {
-                               // Scaling should be done relative to central pixel point
-                               srcPixel = (destPixel + 0.5) * scaleInverted + offset;
-                               srcFirst = Math.max(0, Math.floor(srcPixel - srcWindow));
-                               srcLast = Math.min(srcSize - 1, Math.ceil(srcPixel + srcWindow));
-                               filterElementSize = srcLast - srcFirst + 1;
-                               floatFilter = new Float32Array(filterElementSize);
-                               fxpFilter = new Int16Array(filterElementSize);
-                               total = 0.0; // Fill filter values for calculated range
-                               
-                               for (pxl = srcFirst, idx = 0; pxl <= srcLast; pxl++, idx++) {
-                                       floatVal = filterFunction((pxl + 0.5 - srcPixel) * scaleClamped);
-                                       total += floatVal;
-                                       floatFilter[idx] = floatVal;
-                               } // Normalize filter, convert to fixed point and accumulate conversion error
-                               
-                               
-                               filterTotal = 0;
-                               
-                               for (idx = 0; idx < floatFilter.length; idx++) {
-                                       filterVal = floatFilter[idx] / total;
-                                       filterTotal += filterVal;
-                                       fxpFilter[idx] = toFixedPoint(filterVal);
-                               } // Compensate normalization error, to minimize brightness drift
-                               
-                               
-                               fxpFilter[destSize >> 1] += toFixedPoint(1.0 - filterTotal); //
-                               // Now pack filter to useable form
-                               //
-                               // 1. Trim heading and tailing zero values, and compensate shitf/length
-                               // 2. Put all to single array in this format:
-                               //
-                               //    [ pos shift, data length, value1, value2, value3, ... ]
-                               //
-                               
-                               leftNotEmpty = 0;
-                               
-                               while (leftNotEmpty < fxpFilter.length && fxpFilter[leftNotEmpty] === 0) {
-                                       leftNotEmpty++;
-                               }
-                               
-                               if (leftNotEmpty < fxpFilter.length) {
-                                       rightNotEmpty = fxpFilter.length - 1;
-                                       
-                                       while (rightNotEmpty > 0 && fxpFilter[rightNotEmpty] === 0) {
-                                               rightNotEmpty--;
-                                       }
-                                       
-                                       filterShift = srcFirst + leftNotEmpty;
-                                       filterSize = rightNotEmpty - leftNotEmpty + 1;
-                                       packedFilter[packedFilterPtr++] = filterShift; // shift
-                                       
-                                       packedFilter[packedFilterPtr++] = filterSize; // size
-                                       
-                                       if (!slowCopy) {
-                                               packedFilter.set(fxpFilter.subarray(leftNotEmpty, rightNotEmpty + 1), packedFilterPtr);
-                                               packedFilterPtr += filterSize;
-                                       } else {
-                                               // fallback for old IE < 11, without subarray/set methods
-                                               for (idx = leftNotEmpty; idx <= rightNotEmpty; idx++) {
-                                                       packedFilter[packedFilterPtr++] = fxpFilter[idx];
-                                               }
-                                       }
-                               } else {
-                                       // zero data, write header only
-                                       packedFilter[packedFilterPtr++] = 0; // shift
-                                       
-                                       packedFilter[packedFilterPtr++] = 0; // size
-                               }
-                       }
-                       
-                       return packedFilter;
-               };
-               
-       },{"./resize_filter_info":7}],7:[function(require,module,exports){
+'use strict';
+
+var FILTER_INFO = require('./resize_filter_info'); // Precision of fixed FP values
+
+
+var FIXED_FRAC_BITS = 14;
+
+function toFixedPoint(num) {
+  return Math.round(num * ((1 << FIXED_FRAC_BITS) - 1));
+}
+
+module.exports = function resizeFilterGen(quality, srcSize, destSize, scale, offset) {
+  var filterFunction = FILTER_INFO[quality].filter;
+  var scaleInverted = 1.0 / scale;
+  var scaleClamped = Math.min(1.0, scale); // For upscale
+  // Filter window (averaging interval), scaled to src image
+
+  var srcWindow = FILTER_INFO[quality].win / scaleClamped;
+  var destPixel, srcPixel, srcFirst, srcLast, filterElementSize, floatFilter, fxpFilter, total, pxl, idx, floatVal, filterTotal, filterVal;
+  var leftNotEmpty, rightNotEmpty, filterShift, filterSize;
+  var maxFilterElementSize = Math.floor((srcWindow + 1) * 2);
+  var packedFilter = new Int16Array((maxFilterElementSize + 2) * destSize);
+  var packedFilterPtr = 0;
+  var slowCopy = !packedFilter.subarray || !packedFilter.set; // For each destination pixel calculate source range and built filter values
+
+  for (destPixel = 0; destPixel < destSize; destPixel++) {
+    // Scaling should be done relative to central pixel point
+    srcPixel = (destPixel + 0.5) * scaleInverted + offset;
+    srcFirst = Math.max(0, Math.floor(srcPixel - srcWindow));
+    srcLast = Math.min(srcSize - 1, Math.ceil(srcPixel + srcWindow));
+    filterElementSize = srcLast - srcFirst + 1;
+    floatFilter = new Float32Array(filterElementSize);
+    fxpFilter = new Int16Array(filterElementSize);
+    total = 0.0; // Fill filter values for calculated range
+
+    for (pxl = srcFirst, idx = 0; pxl <= srcLast; pxl++, idx++) {
+      floatVal = filterFunction((pxl + 0.5 - srcPixel) * scaleClamped);
+      total += floatVal;
+      floatFilter[idx] = floatVal;
+    } // Normalize filter, convert to fixed point and accumulate conversion error
+
+
+    filterTotal = 0;
+
+    for (idx = 0; idx < floatFilter.length; idx++) {
+      filterVal = floatFilter[idx] / total;
+      filterTotal += filterVal;
+      fxpFilter[idx] = toFixedPoint(filterVal);
+    } // Compensate normalization error, to minimize brightness drift
+
+
+    fxpFilter[destSize >> 1] += toFixedPoint(1.0 - filterTotal); //
+    // Now pack filter to useable form
+    //
+    // 1. Trim heading and tailing zero values, and compensate shitf/length
+    // 2. Put all to single array in this format:
+    //
+    //    [ pos shift, data length, value1, value2, value3, ... ]
+    //
+
+    leftNotEmpty = 0;
+
+    while (leftNotEmpty < fxpFilter.length && fxpFilter[leftNotEmpty] === 0) {
+      leftNotEmpty++;
+    }
+
+    if (leftNotEmpty < fxpFilter.length) {
+      rightNotEmpty = fxpFilter.length - 1;
+
+      while (rightNotEmpty > 0 && fxpFilter[rightNotEmpty] === 0) {
+        rightNotEmpty--;
+      }
+
+      filterShift = srcFirst + leftNotEmpty;
+      filterSize = rightNotEmpty - leftNotEmpty + 1;
+      packedFilter[packedFilterPtr++] = filterShift; // shift
+
+      packedFilter[packedFilterPtr++] = filterSize; // size
+
+      if (!slowCopy) {
+        packedFilter.set(fxpFilter.subarray(leftNotEmpty, rightNotEmpty + 1), packedFilterPtr);
+        packedFilterPtr += filterSize;
+      } else {
+        // fallback for old IE < 11, without subarray/set methods
+        for (idx = leftNotEmpty; idx <= rightNotEmpty; idx++) {
+          packedFilter[packedFilterPtr++] = fxpFilter[idx];
+        }
+      }
+    } else {
+      // zero data, write header only
+      packedFilter[packedFilterPtr++] = 0; // shift
+
+      packedFilter[packedFilterPtr++] = 0; // size
+    }
+  }
+
+  return packedFilter;
+};
+
+},{"./resize_filter_info":7}],7:[function(require,module,exports){
 // Filter definitions to build tables for
 // resizing convolvers.
 //
 // Presets for quality 0..3. Filter functions + window size
 //
-               'use strict';
-               
-               module.exports = [{
-                       // Nearest neibor (Box)
-                       win: 0.5,
-                       filter: function filter(x) {
-                               return x >= -0.5 && x < 0.5 ? 1.0 : 0.0;
-                       }
-               }, {
-                       // Hamming
-                       win: 1.0,
-                       filter: function filter(x) {
-                               if (x <= -1.0 || x >= 1.0) {
-                                       return 0.0;
-                               }
-                               
-                               if (x > -1.19209290E-07 && x < 1.19209290E-07) {
-                                       return 1.0;
-                               }
-                               
-                               var xpi = x * Math.PI;
-                               return Math.sin(xpi) / xpi * (0.54 + 0.46 * Math.cos(xpi / 1.0));
-                       }
-               }, {
-                       // Lanczos, win = 2
-                       win: 2.0,
-                       filter: function filter(x) {
-                               if (x <= -2.0 || x >= 2.0) {
-                                       return 0.0;
-                               }
-                               
-                               if (x > -1.19209290E-07 && x < 1.19209290E-07) {
-                                       return 1.0;
-                               }
-                               
-                               var xpi = x * Math.PI;
-                               return Math.sin(xpi) / xpi * Math.sin(xpi / 2.0) / (xpi / 2.0);
-                       }
-               }, {
-                       // Lanczos, win = 3
-                       win: 3.0,
-                       filter: function filter(x) {
-                               if (x <= -3.0 || x >= 3.0) {
-                                       return 0.0;
-                               }
-                               
-                               if (x > -1.19209290E-07 && x < 1.19209290E-07) {
-                                       return 1.0;
-                               }
-                               
-                               var xpi = x * Math.PI;
-                               return Math.sin(xpi) / xpi * Math.sin(xpi / 3.0) / (xpi / 3.0);
-                       }
-               }];
-               
-       },{}],8:[function(require,module,exports){
-               'use strict';
-               
-               var createFilters = require('./resize_filter_gen');
-               
-               function resetAlpha(dst, width, height) {
-                       var ptr = 3,
-                               len = width * height * 4 | 0;
-                       
-                       while (ptr < len) {
-                               dst[ptr] = 0xFF;
-                               ptr = ptr + 4 | 0;
-                       }
-               }
-               
-               function asUint8Array(src) {
-                       return new Uint8Array(src.buffer, 0, src.byteLength);
-               }
-               
-               var IS_LE = true; // should not crash everything on module load in old browsers
-               
-               try {
-                       IS_LE = new Uint32Array(new Uint8Array([1, 0, 0, 0]).buffer)[0] === 1;
-               } catch (__) {}
-               
-               function copyInt16asLE(src, target, target_offset) {
-                       if (IS_LE) {
-                               target.set(asUint8Array(src), target_offset);
-                               return;
-                       }
-                       
-                       for (var ptr = target_offset, i = 0; i < src.length; i++) {
-                               var data = src[i];
-                               target[ptr++] = data & 0xFF;
-                               target[ptr++] = data >> 8 & 0xFF;
-                       }
-               }
-               
-               module.exports = function resize_wasm(options) {
-                       var src = options.src;
-                       var srcW = options.width;
-                       var srcH = options.height;
-                       var destW = options.toWidth;
-                       var destH = options.toHeight;
-                       var scaleX = options.scaleX || options.toWidth / options.width;
-                       var scaleY = options.scaleY || options.toHeight / options.height;
-                       var offsetX = options.offsetX || 0.0;
-                       var offsetY = options.offsetY || 0.0;
-                       var dest = options.dest || new Uint8Array(destW * destH * 4);
-                       var quality = typeof options.quality === 'undefined' ? 3 : options.quality;
-                       var alpha = options.alpha || false;
-                       var filtersX = createFilters(quality, srcW, destW, scaleX, offsetX),
-                               filtersY = createFilters(quality, srcH, destH, scaleY, offsetY); // destination is 0 too.
-                       
-                       var src_offset = 0; // buffer between convolve passes
-                       
-                       var tmp_offset = this.__align(src_offset + Math.max(src.byteLength, dest.byteLength));
-                       
-                       var filtersX_offset = this.__align(tmp_offset + srcH * destW * 4);
-                       
-                       var filtersY_offset = this.__align(filtersX_offset + filtersX.byteLength);
-                       
-                       var alloc_bytes = filtersY_offset + filtersY.byteLength;
-                       
-                       var instance = this.__instance('resize', alloc_bytes); //
-                       // Fill memory block with data to process
-                       //
-                       
-                       
-                       var mem = new Uint8Array(this.__memory.buffer);
-                       var mem32 = new Uint32Array(this.__memory.buffer); // 32-bit copy is much faster in chrome
-                       
-                       var src32 = new Uint32Array(src.buffer);
-                       mem32.set(src32); // We should guarantee LE bytes order. Filters are not big, so
-                       // speed difference is not significant vs direct .set()
-                       
-                       copyInt16asLE(filtersX, mem, filtersX_offset);
-                       copyInt16asLE(filtersY, mem, filtersY_offset); //
-                       // Now call webassembly method
-                       // emsdk does method names with '_'
-                       
-                       var fn = instance.exports.convolveHV || instance.exports._convolveHV;
-                       fn(filtersX_offset, filtersY_offset, tmp_offset, srcW, srcH, destW, destH); //
-                       // Copy data back to typed array
-                       //
-                       // 32-bit copy is much faster in chrome
-                       
-                       var dest32 = new Uint32Array(dest.buffer);
-                       dest32.set(new Uint32Array(this.__memory.buffer, 0, destH * destW)); // That's faster than doing checks in convolver.
-                       // !!! Note, canvas data is not premultipled. We don't need other
-                       // alpha corrections.
-                       
-                       if (!alpha) resetAlpha(dest, destW, destH);
-                       return dest;
-               };
-               
-       },{"./resize_filter_gen":6}],9:[function(require,module,exports){
-               'use strict';
-               
-               var GC_INTERVAL = 100;
-               
-               function Pool(create, idle) {
-                       this.create = create;
-                       this.available = [];
-                       this.acquired = {};
-                       this.lastId = 1;
-                       this.timeoutId = 0;
-                       this.idle = idle || 2000;
-               }
-               
-               Pool.prototype.acquire = function () {
-                       var _this = this;
-                       
-                       var resource;
-                       
-                       if (this.available.length !== 0) {
-                               resource = this.available.pop();
-                       } else {
-                               resource = this.create();
-                               resource.id = this.lastId++;
-                               
-                               resource.release = function () {
-                                       return _this.release(resource);
-                               };
-                       }
-                       
-                       this.acquired[resource.id] = resource;
-                       return resource;
-               };
-               
-               Pool.prototype.release = function (resource) {
-                       var _this2 = this;
-                       
-                       delete this.acquired[resource.id];
-                       resource.lastUsed = Date.now();
-                       this.available.push(resource);
-                       
-                       if (this.timeoutId === 0) {
-                               this.timeoutId = setTimeout(function () {
-                                       return _this2.gc();
-                               }, GC_INTERVAL);
-                       }
-               };
-               
-               Pool.prototype.gc = function () {
-                       var _this3 = this;
-                       
-                       var now = Date.now();
-                       this.available = this.available.filter(function (resource) {
-                               if (now - resource.lastUsed > _this3.idle) {
-                                       resource.destroy();
-                                       return false;
-                               }
-                               
-                               return true;
-                       });
-                       
-                       if (this.available.length !== 0) {
-                               this.timeoutId = setTimeout(function () {
-                                       return _this3.gc();
-                               }, GC_INTERVAL);
-                       } else {
-                               this.timeoutId = 0;
-                       }
-               };
-               
-               module.exports = Pool;
-               
-       },{}],10:[function(require,module,exports){
+'use strict';
+
+module.exports = [{
+  // Nearest neibor (Box)
+  win: 0.5,
+  filter: function filter(x) {
+    return x >= -0.5 && x < 0.5 ? 1.0 : 0.0;
+  }
+}, {
+  // Hamming
+  win: 1.0,
+  filter: function filter(x) {
+    if (x <= -1.0 || x >= 1.0) {
+      return 0.0;
+    }
+
+    if (x > -1.19209290E-07 && x < 1.19209290E-07) {
+      return 1.0;
+    }
+
+    var xpi = x * Math.PI;
+    return Math.sin(xpi) / xpi * (0.54 + 0.46 * Math.cos(xpi / 1.0));
+  }
+}, {
+  // Lanczos, win = 2
+  win: 2.0,
+  filter: function filter(x) {
+    if (x <= -2.0 || x >= 2.0) {
+      return 0.0;
+    }
+
+    if (x > -1.19209290E-07 && x < 1.19209290E-07) {
+      return 1.0;
+    }
+
+    var xpi = x * Math.PI;
+    return Math.sin(xpi) / xpi * Math.sin(xpi / 2.0) / (xpi / 2.0);
+  }
+}, {
+  // Lanczos, win = 3
+  win: 3.0,
+  filter: function filter(x) {
+    if (x <= -3.0 || x >= 3.0) {
+      return 0.0;
+    }
+
+    if (x > -1.19209290E-07 && x < 1.19209290E-07) {
+      return 1.0;
+    }
+
+    var xpi = x * Math.PI;
+    return Math.sin(xpi) / xpi * Math.sin(xpi / 3.0) / (xpi / 3.0);
+  }
+}];
+
+},{}],8:[function(require,module,exports){
+'use strict';
+
+var createFilters = require('./resize_filter_gen');
+
+function resetAlpha(dst, width, height) {
+  var ptr = 3,
+      len = width * height * 4 | 0;
+
+  while (ptr < len) {
+    dst[ptr] = 0xFF;
+    ptr = ptr + 4 | 0;
+  }
+}
+
+function asUint8Array(src) {
+  return new Uint8Array(src.buffer, 0, src.byteLength);
+}
+
+var IS_LE = true; // should not crash everything on module load in old browsers
+
+try {
+  IS_LE = new Uint32Array(new Uint8Array([1, 0, 0, 0]).buffer)[0] === 1;
+} catch (__) {}
+
+function copyInt16asLE(src, target, target_offset) {
+  if (IS_LE) {
+    target.set(asUint8Array(src), target_offset);
+    return;
+  }
+
+  for (var ptr = target_offset, i = 0; i < src.length; i++) {
+    var data = src[i];
+    target[ptr++] = data & 0xFF;
+    target[ptr++] = data >> 8 & 0xFF;
+  }
+}
+
+module.exports = function resize_wasm(options) {
+  var src = options.src;
+  var srcW = options.width;
+  var srcH = options.height;
+  var destW = options.toWidth;
+  var destH = options.toHeight;
+  var scaleX = options.scaleX || options.toWidth / options.width;
+  var scaleY = options.scaleY || options.toHeight / options.height;
+  var offsetX = options.offsetX || 0.0;
+  var offsetY = options.offsetY || 0.0;
+  var dest = options.dest || new Uint8Array(destW * destH * 4);
+  var quality = typeof options.quality === 'undefined' ? 3 : options.quality;
+  var alpha = options.alpha || false;
+  var filtersX = createFilters(quality, srcW, destW, scaleX, offsetX),
+      filtersY = createFilters(quality, srcH, destH, scaleY, offsetY); // destination is 0 too.
+
+  var src_offset = 0; // buffer between convolve passes
+
+  var tmp_offset = this.__align(src_offset + Math.max(src.byteLength, dest.byteLength));
+
+  var filtersX_offset = this.__align(tmp_offset + srcH * destW * 4);
+
+  var filtersY_offset = this.__align(filtersX_offset + filtersX.byteLength);
+
+  var alloc_bytes = filtersY_offset + filtersY.byteLength;
+
+  var instance = this.__instance('resize', alloc_bytes); //
+  // Fill memory block with data to process
+  //
+
+
+  var mem = new Uint8Array(this.__memory.buffer);
+  var mem32 = new Uint32Array(this.__memory.buffer); // 32-bit copy is much faster in chrome
+
+  var src32 = new Uint32Array(src.buffer);
+  mem32.set(src32); // We should guarantee LE bytes order. Filters are not big, so
+  // speed difference is not significant vs direct .set()
+
+  copyInt16asLE(filtersX, mem, filtersX_offset);
+  copyInt16asLE(filtersY, mem, filtersY_offset); //
+  // Now call webassembly method
+  // emsdk does method names with '_'
+
+  var fn = instance.exports.convolveHV || instance.exports._convolveHV;
+  fn(filtersX_offset, filtersY_offset, tmp_offset, srcW, srcH, destW, destH); //
+  // Copy data back to typed array
+  //
+  // 32-bit copy is much faster in chrome
+
+  var dest32 = new Uint32Array(dest.buffer);
+  dest32.set(new Uint32Array(this.__memory.buffer, 0, destH * destW)); // That's faster than doing checks in convolver.
+  // !!! Note, canvas data is not premultipled. We don't need other
+  // alpha corrections.
+
+  if (!alpha) resetAlpha(dest, destW, destH);
+  return dest;
+};
+
+},{"./resize_filter_gen":6}],9:[function(require,module,exports){
+'use strict';
+
+var GC_INTERVAL = 100;
+
+function Pool(create, idle) {
+  this.create = create;
+  this.available = [];
+  this.acquired = {};
+  this.lastId = 1;
+  this.timeoutId = 0;
+  this.idle = idle || 2000;
+}
+
+Pool.prototype.acquire = function () {
+  var _this = this;
+
+  var resource;
+
+  if (this.available.length !== 0) {
+    resource = this.available.pop();
+  } else {
+    resource = this.create();
+    resource.id = this.lastId++;
+
+    resource.release = function () {
+      return _this.release(resource);
+    };
+  }
+
+  this.acquired[resource.id] = resource;
+  return resource;
+};
+
+Pool.prototype.release = function (resource) {
+  var _this2 = this;
+
+  delete this.acquired[resource.id];
+  resource.lastUsed = Date.now();
+  this.available.push(resource);
+
+  if (this.timeoutId === 0) {
+    this.timeoutId = setTimeout(function () {
+      return _this2.gc();
+    }, GC_INTERVAL);
+  }
+};
+
+Pool.prototype.gc = function () {
+  var _this3 = this;
+
+  var now = Date.now();
+  this.available = this.available.filter(function (resource) {
+    if (now - resource.lastUsed > _this3.idle) {
+      resource.destroy();
+      return false;
+    }
+
+    return true;
+  });
+
+  if (this.available.length !== 0) {
+    this.timeoutId = setTimeout(function () {
+      return _this3.gc();
+    }, GC_INTERVAL);
+  } else {
+    this.timeoutId = 0;
+  }
+};
+
+module.exports = Pool;
+
+},{}],10:[function(require,module,exports){
 // Add intermediate resizing steps when scaling down by a very large factor.
 //
 // For example, when resizing 10000x10000 down to 10x10, it'll resize it to
@@ -618,640 +597,646 @@ THE SOFTWARE. */
 // Also, adding intermediate steps can speed up processing if we use lower
 // quality algorithms for first stages.
 //
-               'use strict'; // min size = 0 results in infinite loop,
+'use strict'; // min size = 0 results in infinite loop,
 // min size = 1 can consume large amount of memory
-               
-               var MIN_INNER_TILE_SIZE = 2;
-               
-               module.exports = function createStages(fromWidth, fromHeight, toWidth, toHeight, srcTileSize, destTileBorder) {
-                       var scaleX = toWidth / fromWidth;
-                       var scaleY = toHeight / fromHeight; // derived from createRegions equation:
-                       // innerTileWidth = pixelFloor(srcTileSize * scaleX) - 2 * destTileBorder;
-                       
-                       var minScale = (2 * destTileBorder + MIN_INNER_TILE_SIZE + 1) / srcTileSize; // refuse to scale image multiple times by less than twice each time,
-                       // it could only happen because of invalid options
-                       
-                       if (minScale > 0.5) return [[toWidth, toHeight]];
-                       var stageCount = Math.ceil(Math.log(Math.min(scaleX, scaleY)) / Math.log(minScale)); // no additional resizes are necessary,
-                       // stageCount can be zero or be negative when enlarging the image
-                       
-                       if (stageCount <= 1) return [[toWidth, toHeight]];
-                       var result = [];
-                       
-                       for (var i = 0; i < stageCount; i++) {
-                               var width = Math.round(Math.pow(Math.pow(fromWidth, stageCount - i - 1) * Math.pow(toWidth, i + 1), 1 / stageCount));
-                               var height = Math.round(Math.pow(Math.pow(fromHeight, stageCount - i - 1) * Math.pow(toHeight, i + 1), 1 / stageCount));
-                               result.push([width, height]);
-                       }
-                       
-                       return result;
-               };
-               
-       },{}],11:[function(require,module,exports){
+
+var MIN_INNER_TILE_SIZE = 2;
+
+module.exports = function createStages(fromWidth, fromHeight, toWidth, toHeight, srcTileSize, destTileBorder) {
+  var scaleX = toWidth / fromWidth;
+  var scaleY = toHeight / fromHeight; // derived from createRegions equation:
+  // innerTileWidth = pixelFloor(srcTileSize * scaleX) - 2 * destTileBorder;
+
+  var minScale = (2 * destTileBorder + MIN_INNER_TILE_SIZE + 1) / srcTileSize; // refuse to scale image multiple times by less than twice each time,
+  // it could only happen because of invalid options
+
+  if (minScale > 0.5) return [[toWidth, toHeight]];
+  var stageCount = Math.ceil(Math.log(Math.min(scaleX, scaleY)) / Math.log(minScale)); // no additional resizes are necessary,
+  // stageCount can be zero or be negative when enlarging the image
+
+  if (stageCount <= 1) return [[toWidth, toHeight]];
+  var result = [];
+
+  for (var i = 0; i < stageCount; i++) {
+    var width = Math.round(Math.pow(Math.pow(fromWidth, stageCount - i - 1) * Math.pow(toWidth, i + 1), 1 / stageCount));
+    var height = Math.round(Math.pow(Math.pow(fromHeight, stageCount - i - 1) * Math.pow(toHeight, i + 1), 1 / stageCount));
+    result.push([width, height]);
+  }
+
+  return result;
+};
+
+},{}],11:[function(require,module,exports){
 // Split original image into multiple 1024x1024 chunks to reduce memory usage
 // (images have to be unpacked into typed arrays for resizing) and allow
 // parallel processing of multiple tiles at a time.
 //
-               'use strict';
-               /*
               * pixelFloor and pixelCeil are modified versions of Math.floor and Math.ceil
               * functions which take into account floating point arithmetic errors.
               * Those errors can cause undesired increments/decrements of sizes and offsets:
               * Math.ceil(36 / (36 / 500)) = 501
               * pixelCeil(36 / (36 / 500)) = 500
               */
-               
-               var PIXEL_EPSILON = 1e-5;
-               
-               function pixelFloor(x) {
-                       var nearest = Math.round(x);
-                       
-                       if (Math.abs(x - nearest) < PIXEL_EPSILON) {
-                               return nearest;
-                       }
-                       
-                       return Math.floor(x);
-               }
-               
-               function pixelCeil(x) {
-                       var nearest = Math.round(x);
-                       
-                       if (Math.abs(x - nearest) < PIXEL_EPSILON) {
-                               return nearest;
-                       }
-                       
-                       return Math.ceil(x);
-               }
-               
-               module.exports = function createRegions(options) {
-                       var scaleX = options.toWidth / options.width;
-                       var scaleY = options.toHeight / options.height;
-                       var innerTileWidth = pixelFloor(options.srcTileSize * scaleX) - 2 * options.destTileBorder;
-                       var innerTileHeight = pixelFloor(options.srcTileSize * scaleY) - 2 * options.destTileBorder; // prevent infinite loop, this should never happen
-                       
-                       if (innerTileWidth < 1 || innerTileHeight < 1) {
-                               throw new Error('Internal error in pica: target tile width/height is too small.');
-                       }
-                       
-                       var x, y;
-                       var innerX, innerY, toTileWidth, toTileHeight;
-                       var tiles = [];
-                       var tile; // we go top-to-down instead of left-to-right to make image displayed from top to
-                       // doesn in the browser
-                       
-                       for (innerY = 0; innerY < options.toHeight; innerY += innerTileHeight) {
-                               for (innerX = 0; innerX < options.toWidth; innerX += innerTileWidth) {
-                                       x = innerX - options.destTileBorder;
-                                       
-                                       if (x < 0) {
-                                               x = 0;
-                                       }
-                                       
-                                       toTileWidth = innerX + innerTileWidth + options.destTileBorder - x;
-                                       
-                                       if (x + toTileWidth >= options.toWidth) {
-                                               toTileWidth = options.toWidth - x;
-                                       }
-                                       
-                                       y = innerY - options.destTileBorder;
-                                       
-                                       if (y < 0) {
-                                               y = 0;
-                                       }
-                                       
-                                       toTileHeight = innerY + innerTileHeight + options.destTileBorder - y;
-                                       
-                                       if (y + toTileHeight >= options.toHeight) {
-                                               toTileHeight = options.toHeight - y;
-                                       }
-                                       
-                                       tile = {
-                                               toX: x,
-                                               toY: y,
-                                               toWidth: toTileWidth,
-                                               toHeight: toTileHeight,
-                                               toInnerX: innerX,
-                                               toInnerY: innerY,
-                                               toInnerWidth: innerTileWidth,
-                                               toInnerHeight: innerTileHeight,
-                                               offsetX: x / scaleX - pixelFloor(x / scaleX),
-                                               offsetY: y / scaleY - pixelFloor(y / scaleY),
-                                               scaleX: scaleX,
-                                               scaleY: scaleY,
-                                               x: pixelFloor(x / scaleX),
-                                               y: pixelFloor(y / scaleY),
-                                               width: pixelCeil(toTileWidth / scaleX),
-                                               height: pixelCeil(toTileHeight / scaleY)
-                                       };
-                                       tiles.push(tile);
-                               }
-                       }
-                       
-                       return tiles;
-               };
-               
-       },{}],12:[function(require,module,exports){
-               'use strict';
-               
-               function objClass(obj) {
-                       return Object.prototype.toString.call(obj);
-               }
-               
-               module.exports.isCanvas = function isCanvas(element) {
-                       //return (element.nodeName && element.nodeName.toLowerCase() === 'canvas') ||
-                       var cname = objClass(element);
-                       return cname === '[object HTMLCanvasElement]'
-                               /* browser */
-                               || cname === '[object Canvas]'
-                               /* node-canvas */
-                               ;
-               };
-               
-               module.exports.isImage = function isImage(element) {
-                       //return element.nodeName && element.nodeName.toLowerCase() === 'img';
-                       return objClass(element) === '[object HTMLImageElement]';
-               };
-               
-               module.exports.limiter = function limiter(concurrency) {
-                       var active = 0,
-                               queue = [];
-                       
-                       function roll() {
-                               if (active < concurrency && queue.length) {
-                                       active++;
-                                       queue.shift()();
-                               }
-                       }
-                       
-                       return function limit(fn) {
-                               return new Promise(function (resolve, reject) {
-                                       queue.push(function () {
-                                               fn().then(function (result) {
-                                                       resolve(result);
-                                                       active--;
-                                                       roll();
-                                               }, function (err) {
-                                                       reject(err);
-                                                       active--;
-                                                       roll();
-                                               });
-                                       });
-                                       roll();
-                               });
-                       };
-               };
-               
-               module.exports.cib_quality_name = function cib_quality_name(num) {
-                       switch (num) {
-                               case 0:
-                                       return 'pixelated';
-                               
-                               case 1:
-                                       return 'low';
-                               
-                               case 2:
-                                       return 'medium';
-                       }
-                       
-                       return 'high';
-               };
-               
-               module.exports.cib_support = function cib_support() {
-                       return Promise.resolve().then(function () {
-                               if (typeof createImageBitmap === 'undefined' || typeof document === 'undefined') {
-                                       return false;
-                               }
-                               
-                               var c = document.createElement('canvas');
-                               c.width = 100;
-                               c.height = 100;
-                               return createImageBitmap(c, 0, 0, 100, 100, {
-                                       resizeWidth: 10,
-                                       resizeHeight: 10,
-                                       resizeQuality: 'high'
-                               }).then(function (bitmap) {
-                                       var status = bitmap.width === 10; // Branch below is filtered on upper level. We do not call resize
-                                       // detection for basic ImageBitmap.
-                                       //
-                                       // https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap
-                                       // old Crome 51 has ImageBitmap without .close(). Then this code
-                                       // will throw and return 'false' as expected.
-                                       //
-                                       
-                                       bitmap.close();
-                                       c = null;
-                                       return status;
-                               });
-                       }).catch(function () {
-                               return false;
-                       });
-               };
-               
-       },{}],13:[function(require,module,exports){
+'use strict';
+/*
+ * pixelFloor and pixelCeil are modified versions of Math.floor and Math.ceil
+ * functions which take into account floating point arithmetic errors.
+ * Those errors can cause undesired increments/decrements of sizes and offsets:
+ * Math.ceil(36 / (36 / 500)) = 501
+ * pixelCeil(36 / (36 / 500)) = 500
+ */
+
+var PIXEL_EPSILON = 1e-5;
+
+function pixelFloor(x) {
+  var nearest = Math.round(x);
+
+  if (Math.abs(x - nearest) < PIXEL_EPSILON) {
+    return nearest;
+  }
+
+  return Math.floor(x);
+}
+
+function pixelCeil(x) {
+  var nearest = Math.round(x);
+
+  if (Math.abs(x - nearest) < PIXEL_EPSILON) {
+    return nearest;
+  }
+
+  return Math.ceil(x);
+}
+
+module.exports = function createRegions(options) {
+  var scaleX = options.toWidth / options.width;
+  var scaleY = options.toHeight / options.height;
+  var innerTileWidth = pixelFloor(options.srcTileSize * scaleX) - 2 * options.destTileBorder;
+  var innerTileHeight = pixelFloor(options.srcTileSize * scaleY) - 2 * options.destTileBorder; // prevent infinite loop, this should never happen
+
+  if (innerTileWidth < 1 || innerTileHeight < 1) {
+    throw new Error('Internal error in pica: target tile width/height is too small.');
+  }
+
+  var x, y;
+  var innerX, innerY, toTileWidth, toTileHeight;
+  var tiles = [];
+  var tile; // we go top-to-down instead of left-to-right to make image displayed from top to
+  // doesn in the browser
+
+  for (innerY = 0; innerY < options.toHeight; innerY += innerTileHeight) {
+    for (innerX = 0; innerX < options.toWidth; innerX += innerTileWidth) {
+      x = innerX - options.destTileBorder;
+
+      if (x < 0) {
+        x = 0;
+      }
+
+      toTileWidth = innerX + innerTileWidth + options.destTileBorder - x;
+
+      if (x + toTileWidth >= options.toWidth) {
+        toTileWidth = options.toWidth - x;
+      }
+
+      y = innerY - options.destTileBorder;
+
+      if (y < 0) {
+        y = 0;
+      }
+
+      toTileHeight = innerY + innerTileHeight + options.destTileBorder - y;
+
+      if (y + toTileHeight >= options.toHeight) {
+        toTileHeight = options.toHeight - y;
+      }
+
+      tile = {
+        toX: x,
+        toY: y,
+        toWidth: toTileWidth,
+        toHeight: toTileHeight,
+        toInnerX: innerX,
+        toInnerY: innerY,
+        toInnerWidth: innerTileWidth,
+        toInnerHeight: innerTileHeight,
+        offsetX: x / scaleX - pixelFloor(x / scaleX),
+        offsetY: y / scaleY - pixelFloor(y / scaleY),
+        scaleX: scaleX,
+        scaleY: scaleY,
+        x: pixelFloor(x / scaleX),
+        y: pixelFloor(y / scaleY),
+        width: pixelCeil(toTileWidth / scaleX),
+        height: pixelCeil(toTileHeight / scaleY)
+      };
+      tiles.push(tile);
+    }
+  }
+
+  return tiles;
+};
+
+},{}],12:[function(require,module,exports){
+'use strict';
+
+function objClass(obj) {
+  return Object.prototype.toString.call(obj);
+}
+
+module.exports.isCanvas = function isCanvas(element) {
+  //return (element.nodeName && element.nodeName.toLowerCase() === 'canvas') ||
+  var cname = objClass(element);
+  return cname === '[object HTMLCanvasElement]'
+  /* browser */
+  || cname === '[object Canvas]'
+  /* node-canvas */
+  ;
+};
+
+module.exports.isImage = function isImage(element) {
+  //return element.nodeName && element.nodeName.toLowerCase() === 'img';
+  return objClass(element) === '[object HTMLImageElement]';
+};
+
+module.exports.limiter = function limiter(concurrency) {
+  var active = 0,
+      queue = [];
+
+  function roll() {
+    if (active < concurrency && queue.length) {
+      active++;
+      queue.shift()();
+    }
+  }
+
+  return function limit(fn) {
+    return new Promise(function (resolve, reject) {
+      queue.push(function () {
+        fn().then(function (result) {
+          resolve(result);
+          active--;
+          roll();
+        }, function (err) {
+          reject(err);
+          active--;
+          roll();
+        });
+      });
+      roll();
+    });
+  };
+};
+
+module.exports.cib_quality_name = function cib_quality_name(num) {
+  switch (num) {
+    case 0:
+      return 'pixelated';
+
+    case 1:
+      return 'low';
+
+    case 2:
+      return 'medium';
+  }
+
+  return 'high';
+};
+
+module.exports.cib_support = function cib_support() {
+  return Promise.resolve().then(function () {
+    if (typeof createImageBitmap === 'undefined' || typeof document === 'undefined') {
+      return false;
+    }
+
+    var c = document.createElement('canvas');
+    c.width = 100;
+    c.height = 100;
+    return createImageBitmap(c, 0, 0, 100, 100, {
+      resizeWidth: 10,
+      resizeHeight: 10,
+      resizeQuality: 'high'
+    }).then(function (bitmap) {
+      var status = bitmap.width === 10; // Branch below is filtered on upper level. We do not call resize
+      // detection for basic ImageBitmap.
+      //
+      // https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap
+      // old Crome 51 has ImageBitmap without .close(). Then this code
+      // will throw and return 'false' as expected.
+      //
+
+      bitmap.close();
+      c = null;
+      return status;
+    });
+  })["catch"](function () {
+    return false;
+  });
+};
+
+},{}],13:[function(require,module,exports){
 // Web Worker wrapper for image resize function
-               'use strict';
-               
-               module.exports = function () {
-                       var MathLib = require('./mathlib');
-                       
-                       var mathLib;
-                       /* eslint-disable no-undef */
-                       
-                       onmessage = function onmessage(ev) {
-                               var opts = ev.data.opts;
-                               if (!mathLib) mathLib = new MathLib(ev.data.features); // Use multimath's sync auto-init. Avoid Promise use in old browsers,
-                               // because polyfills are not propagated to webworker.
-                               
-                               var result = mathLib.resizeAndUnsharp(opts);
-                               postMessage({
-                                       result: result
-                               }, [result.buffer]);
-                       };
-               };
-               
-       },{"./mathlib":1}],14:[function(require,module,exports){
+'use strict';
+
+module.exports = function () {
+  var MathLib = require('./mathlib');
+
+  var mathLib;
+  /* eslint-disable no-undef */
+
+  onmessage = function onmessage(ev) {
+    var opts = ev.data.opts;
+    if (!mathLib) mathLib = new MathLib(ev.data.features); // Use multimath's sync auto-init. Avoid Promise use in old browsers,
+    // because polyfills are not propagated to webworker.
+
+    var result = mathLib.resizeAndUnsharp(opts);
+    postMessage({
+      result: result
+    }, [result.buffer]);
+  };
+};
+
+},{"./mathlib":1}],14:[function(require,module,exports){
 // Calculate Gaussian blur of an image using IIR filter
 // The method is taken from Intel's white paper and code example attached to it:
 // https://software.intel.com/en-us/articles/iir-gaussian-blur-filter
 // -implementation-using-intel-advanced-vector-extensions
-               
-               var a0, a1, a2, a3, b1, b2, left_corner, right_corner;
-               
-               function gaussCoef(sigma) {
-                       if (sigma < 0.5) {
-                               sigma = 0.5;
-                       }
-                       
-                       var a = Math.exp(0.726 * 0.726) / sigma,
-                               g1 = Math.exp(-a),
-                               g2 = Math.exp(-2 * a),
-                               k = (1 - g1) * (1 - g1) / (1 + 2 * a * g1 - g2);
-                       
-                       a0 = k;
-                       a1 = k * (a - 1) * g1;
-                       a2 = k * (a + 1) * g1;
-                       a3 = -k * g2;
-                       b1 = 2 * g1;
-                       b2 = -g2;
-                       left_corner = (a0 + a1) / (1 - b1 - b2);
-                       right_corner = (a2 + a3) / (1 - b1 - b2);
-                       
-                       // Attempt to force type to FP32.
-                       return new Float32Array([ a0, a1, a2, a3, b1, b2, left_corner, right_corner ]);
-               }
-               
-               function convolveMono16(src, out, line, coeff, width, height) {
-                       // takes src image and writes the blurred and transposed result into out
-                       
-                       var prev_src, curr_src, curr_out, prev_out, prev_prev_out;
-                       var src_index, out_index, line_index;
-                       var i, j;
-                       var coeff_a0, coeff_a1, coeff_b1, coeff_b2;
-                       
-                       for (i = 0; i < height; i++) {
-                               src_index = i * width;
-                               out_index = i;
-                               line_index = 0;
-                               
-                               // left to right
-                               prev_src = src[src_index];
-                               prev_prev_out = prev_src * coeff[6];
-                               prev_out = prev_prev_out;
-                               
-                               coeff_a0 = coeff[0];
-                               coeff_a1 = coeff[1];
-                               coeff_b1 = coeff[4];
-                               coeff_b2 = coeff[5];
-                               
-                               for (j = 0; j < width; j++) {
-                                       curr_src = src[src_index];
-                                       
-                                       curr_out = curr_src * coeff_a0 +
-                                               prev_src * coeff_a1 +
-                                               prev_out * coeff_b1 +
-                                               prev_prev_out * coeff_b2;
-                                       
-                                       prev_prev_out = prev_out;
-                                       prev_out = curr_out;
-                                       prev_src = curr_src;
-                                       
-                                       line[line_index] = prev_out;
-                                       line_index++;
-                                       src_index++;
-                               }
-                               
-                               src_index--;
-                               line_index--;
-                               out_index += height * (width - 1);
-                               
-                               // right to left
-                               prev_src = src[src_index];
-                               prev_prev_out = prev_src * coeff[7];
-                               prev_out = prev_prev_out;
-                               curr_src = prev_src;
-                               
-                               coeff_a0 = coeff[2];
-                               coeff_a1 = coeff[3];
-                               
-                               for (j = width - 1; j >= 0; j--) {
-                                       curr_out = curr_src * coeff_a0 +
-                                               prev_src * coeff_a1 +
-                                               prev_out * coeff_b1 +
-                                               prev_prev_out * coeff_b2;
-                                       
-                                       prev_prev_out = prev_out;
-                                       prev_out = curr_out;
-                                       
-                                       prev_src = curr_src;
-                                       curr_src = src[src_index];
-                                       
-                                       out[out_index] = line[line_index] + prev_out;
-                                       
-                                       src_index--;
-                                       line_index--;
-                                       out_index -= height;
-                               }
-                       }
-               }
-               
-               
-               function blurMono16(src, width, height, radius) {
-                       // Quick exit on zero radius
-                       if (!radius) { return; }
-                       
-                       var out      = new Uint16Array(src.length),
-                               tmp_line = new Float32Array(Math.max(width, height));
-                       
-                       var coeff = gaussCoef(radius);
-                       
-                       convolveMono16(src, out, tmp_line, coeff, width, height, radius);
-                       convolveMono16(out, src, tmp_line, coeff, height, width, radius);
-               }
-               
-               module.exports = blurMono16;
-               
-       },{}],15:[function(require,module,exports){
-               if (typeof Object.create === 'function') {
-                       // implementation from standard node.js 'util' module
-                       module.exports = function inherits(ctor, superCtor) {
-                               ctor.super_ = superCtor
-                               ctor.prototype = Object.create(superCtor.prototype, {
-                                       constructor: {
-                                               value: ctor,
-                                               enumerable: false,
-                                               writable: true,
-                                               configurable: true
-                                       }
-                               });
-                       };
-               } else {
-                       // old school shim for old browsers
-                       module.exports = function inherits(ctor, superCtor) {
-                               ctor.super_ = superCtor
-                               var TempCtor = function () {}
-                               TempCtor.prototype = superCtor.prototype
-                               ctor.prototype = new TempCtor()
-                               ctor.prototype.constructor = ctor
-                       }
-               }
-               
-       },{}],16:[function(require,module,exports){
-               'use strict';
-               
-               
-               var assign         = require('object-assign');
-               var base64decode   = require('./lib/base64decode');
-               var hasWebAssembly = require('./lib/wa_detect');
-               
-               
-               var DEFAULT_OPTIONS = {
-                       js: true,
-                       wasm: true
-               };
-               
-               
-               function MultiMath(options) {
-                       if (!(this instanceof MultiMath)) return new MultiMath(options);
-                       
-                       var opts = assign({}, DEFAULT_OPTIONS, options || {});
-                       
-                       this.options         = opts;
-                       
-                       this.__cache         = {};
-                       this.has_wasm        = hasWebAssembly();
-                       
-                       this.__init_promise  = null;
-                       this.__modules       = opts.modules || {};
-                       this.__memory        = null;
-                       this.__wasm          = {};
-                       
-                       this.__isLE = ((new Uint32Array((new Uint8Array([ 1, 0, 0, 0 ])).buffer))[0] === 1);
-                       
-                       if (!this.options.js && !this.options.wasm) {
-                               throw new Error('mathlib: at least "js" or "wasm" should be enabled');
-                       }
-               }
-               
-               
-               MultiMath.prototype.use = function (module) {
-                       this.__modules[module.name] = module;
-                       
-                       // Pin the best possible implementation
-                       if (!this.has_wasm || !this.options.wasm || !module.wasm_fn) {
-                               this[module.name] = module.fn;
-                       } else {
-                               this[module.name] = module.wasm_fn;
-                       }
-                       
-                       return this;
-               };
-               
-               
-               MultiMath.prototype.init = function () {
-                       if (this.__init_promise) return this.__init_promise;
-                       
-                       if (!this.options.js && this.options.wasm && !this.has_wasm) {
-                               return Promise.reject(new Error('mathlib: only "wasm" was enabled, but it\'s not supported'));
-                       }
-                       
-                       var self = this;
-                       
-                       this.__init_promise = Promise.all(Object.keys(self.__modules).map(function (name) {
-                                       var module = self.__modules[name];
-                                       
-                                       if (!self.has_wasm || !self.options.wasm || !module.wasm_fn) return null;
-                                       
-                                       // If already compiled - exit
-                                       if (self.__wasm[name]) return null;
-                                       
-                                       // Compile wasm source
-                                       return WebAssembly.compile(self.__base64decode(module.wasm_src))
-                                               .then(function (m) { self.__wasm[name] = m; });
-                               }))
-                               .then(function () { return self; });
-                       
-                       return this.__init_promise;
-               };
 
+var a0, a1, a2, a3, b1, b2, left_corner, right_corner;
 
-////////////////////////////////////////////////////////////////////////////////
-// Methods below are for internal use from plugins
+function gaussCoef(sigma) {
+  if (sigma < 0.5) {
+    sigma = 0.5;
+  }
 
+  var a = Math.exp(0.726 * 0.726) / sigma,
+      g1 = Math.exp(-a),
+      g2 = Math.exp(-2 * a),
+      k = (1 - g1) * (1 - g1) / (1 + 2 * a * g1 - g2);
 
-// Simple decode base64 to typed array. Useful to load embedded webassembly
-// code. You probably don't need to call this method directly.
-//
-               MultiMath.prototype.__base64decode = base64decode;
+  a0 = k;
+  a1 = k * (a - 1) * g1;
+  a2 = k * (a + 1) * g1;
+  a3 = -k * g2;
+  b1 = 2 * g1;
+  b2 = -g2;
+  left_corner = (a0 + a1) / (1 - b1 - b2);
+  right_corner = (a2 + a3) / (1 - b1 - b2);
 
+  // Attempt to force type to FP32.
+  return new Float32Array([ a0, a1, a2, a3, b1, b2, left_corner, right_corner ]);
+}
 
-// Increase current memory to include specified number of bytes. Do nothing if
-// size is already ok. You probably don't need to call this method directly,
-// because it will be invoked from `.__instance()`.
-//
-               MultiMath.prototype.__reallocate = function mem_grow_to(bytes) {
-                       if (!this.__memory) {
-                               this.__memory = new WebAssembly.Memory({
-                                       initial: Math.ceil(bytes / (64 * 1024))
-                               });
-                               return this.__memory;
-                       }
-                       
-                       var mem_size = this.__memory.buffer.byteLength;
-                       
-                       if (mem_size < bytes) {
-                               this.__memory.grow(Math.ceil((bytes - mem_size) / (64 * 1024)));
-                       }
-                       
-                       return this.__memory;
-               };
+function convolveMono16(src, out, line, coeff, width, height) {
+  // takes src image and writes the blurred and transposed result into out
 
+  var prev_src, curr_src, curr_out, prev_out, prev_prev_out;
+  var src_index, out_index, line_index;
+  var i, j;
+  var coeff_a0, coeff_a1, coeff_b1, coeff_b2;
 
-// Returns instantinated webassembly item by name, with specified memory size
-// and environment.
-// - use cache if available
-// - do sync module init, if async init was not called earlier
-// - allocate memory if not enougth
-// - can export functions to webassembly via "env_extra",
-//   for example, { exp: Math.exp }
-//
-               MultiMath.prototype.__instance = function instance(name, memsize, env_extra) {
-                       if (memsize) this.__reallocate(memsize);
-                       
-                       // If .init() was not called, do sync compile
-                       if (!this.__wasm[name]) {
-                               var module = this.__modules[name];
-                               this.__wasm[name] = new WebAssembly.Module(this.__base64decode(module.wasm_src));
-                       }
-                       
-                       if (!this.__cache[name]) {
-                               var env_base = {
-                                       memoryBase: 0,
-                                       memory: this.__memory,
-                                       tableBase: 0,
-                                       table: new WebAssembly.Table({ initial: 0, element: 'anyfunc' })
-                               };
-                               
-                               this.__cache[name] = new WebAssembly.Instance(this.__wasm[name], {
-                                       env: assign(env_base, env_extra || {})
-                               });
-                       }
-                       
-                       return this.__cache[name];
-               };
+  for (i = 0; i < height; i++) {
+    src_index = i * width;
+    out_index = i;
+    line_index = 0;
 
+    // left to right
+    prev_src = src[src_index];
+    prev_prev_out = prev_src * coeff[6];
+    prev_out = prev_prev_out;
 
-// Helper to calculate memory aligh for pointers. Webassembly does not require
-// this, but you may wish to experiment. Default base = 8;
-//
-               MultiMath.prototype.__align = function align(number, base) {
-                       base = base || 8;
-                       var reminder = number % base;
-                       return number + (reminder ? base - reminder : 0);
-               };
-               
-               
-               module.exports = MultiMath;
-               
-       },{"./lib/base64decode":17,"./lib/wa_detect":23,"object-assign":24}],17:[function(require,module,exports){
-// base64 decode str -> Uint8Array, to load WA modules
-//
-               'use strict';
-               
-               
-               var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
-               
-               
-               module.exports = function base64decode(str) {
-                       var input = str.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
-                               max   = input.length;
-                       
-                       var out = new Uint8Array((max * 3) >> 2);
-                       
-                       // Collect by 6*4 bits (3 bytes)
-                       
-                       var bits = 0;
-                       var ptr  = 0;
-                       
-                       for (var idx = 0; idx < max; idx++) {
-                               if ((idx % 4 === 0) && idx) {
-                                       out[ptr++] = (bits >> 16) & 0xFF;
-                                       out[ptr++] = (bits >> 8) & 0xFF;
-                                       out[ptr++] = bits & 0xFF;
-                               }
-                               
-                               bits = (bits << 6) | BASE64_MAP.indexOf(input.charAt(idx));
-                       }
-                       
-                       // Dump tail
-                       
-                       var tailbits = (max % 4) * 6;
-                       
-                       if (tailbits === 0) {
-                               out[ptr++] = (bits >> 16) & 0xFF;
-                               out[ptr++] = (bits >> 8) & 0xFF;
-                               out[ptr++] = bits & 0xFF;
-                       } else if (tailbits === 18) {
-                               out[ptr++] = (bits >> 10) & 0xFF;
-                               out[ptr++] = (bits >> 2) & 0xFF;
-                       } else if (tailbits === 12) {
-                               out[ptr++] = (bits >> 4) & 0xFF;
-                       }
-                       
-                       return out;
-               };
-               
-       },{}],18:[function(require,module,exports){
-// Calculates 16-bit precision HSL lightness from 8-bit rgba buffer
-//
-               'use strict';
-               
-               
-               module.exports = function hsl_l16_js(img, width, height) {
-                       var size = width * height;
-                       var out = new Uint16Array(size);
-                       var r, g, b, min, max;
-                       for (var i = 0; i < size; i++) {
-                               r = img[4 * i];
-                               g = img[4 * i + 1];
-                               b = img[4 * i + 2];
-                               max = (r >= g && r >= b) ? r : (g >= b && g >= r) ? g : b;
-                               min = (r <= g && r <= b) ? r : (g <= b && g <= r) ? g : b;
-                               out[i] = (max + min) * 257 >> 1;
-                       }
-                       return out;
-               };
-               
-       },{}],19:[function(require,module,exports){
-               'use strict';
-               
-               module.exports = {
-                       name:     'unsharp_mask',
-                       fn:       require('./unsharp_mask'),
-                       wasm_fn:  require('./unsharp_mask_wasm'),
-                       wasm_src: require('./unsharp_mask_wasm_base64')
-               };
-               
-       },{"./unsharp_mask":20,"./unsharp_mask_wasm":21,"./unsharp_mask_wasm_base64":22}],20:[function(require,module,exports){
+    coeff_a0 = coeff[0];
+    coeff_a1 = coeff[1];
+    coeff_b1 = coeff[4];
+    coeff_b2 = coeff[5];
+
+    for (j = 0; j < width; j++) {
+      curr_src = src[src_index];
+
+      curr_out = curr_src * coeff_a0 +
+                 prev_src * coeff_a1 +
+                 prev_out * coeff_b1 +
+                 prev_prev_out * coeff_b2;
+
+      prev_prev_out = prev_out;
+      prev_out = curr_out;
+      prev_src = curr_src;
+
+      line[line_index] = prev_out;
+      line_index++;
+      src_index++;
+    }
+
+    src_index--;
+    line_index--;
+    out_index += height * (width - 1);
+
+    // right to left
+    prev_src = src[src_index];
+    prev_prev_out = prev_src * coeff[7];
+    prev_out = prev_prev_out;
+    curr_src = prev_src;
+
+    coeff_a0 = coeff[2];
+    coeff_a1 = coeff[3];
+
+    for (j = width - 1; j >= 0; j--) {
+      curr_out = curr_src * coeff_a0 +
+                 prev_src * coeff_a1 +
+                 prev_out * coeff_b1 +
+                 prev_prev_out * coeff_b2;
+
+      prev_prev_out = prev_out;
+      prev_out = curr_out;
+
+      prev_src = curr_src;
+      curr_src = src[src_index];
+
+      out[out_index] = line[line_index] + prev_out;
+
+      src_index--;
+      line_index--;
+      out_index -= height;
+    }
+  }
+}
+
+
+function blurMono16(src, width, height, radius) {
+  // Quick exit on zero radius
+  if (!radius) { return; }
+
+  var out      = new Uint16Array(src.length),
+      tmp_line = new Float32Array(Math.max(width, height));
+
+  var coeff = gaussCoef(radius);
+
+  convolveMono16(src, out, tmp_line, coeff, width, height, radius);
+  convolveMono16(out, src, tmp_line, coeff, height, width, radius);
+}
+
+module.exports = blurMono16;
+
+},{}],15:[function(require,module,exports){
+if (typeof Object.create === 'function') {
+  // implementation from standard node.js 'util' module
+  module.exports = function inherits(ctor, superCtor) {
+    if (superCtor) {
+      ctor.super_ = superCtor
+      ctor.prototype = Object.create(superCtor.prototype, {
+        constructor: {
+          value: ctor,
+          enumerable: false,
+          writable: true,
+          configurable: true
+        }
+      })
+    }
+  };
+} else {
+  // old school shim for old browsers
+  module.exports = function inherits(ctor, superCtor) {
+    if (superCtor) {
+      ctor.super_ = superCtor
+      var TempCtor = function () {}
+      TempCtor.prototype = superCtor.prototype
+      ctor.prototype = new TempCtor()
+      ctor.prototype.constructor = ctor
+    }
+  }
+}
+
+},{}],16:[function(require,module,exports){
+'use strict';
+
+
+var assign         = require('object-assign');
+var base64decode   = require('./lib/base64decode');
+var hasWebAssembly = require('./lib/wa_detect');
+
+
+var DEFAULT_OPTIONS = {
+  js: true,
+  wasm: true
+};
+
+
+function MultiMath(options) {
+  if (!(this instanceof MultiMath)) return new MultiMath(options);
+
+  var opts = assign({}, DEFAULT_OPTIONS, options || {});
+
+  this.options         = opts;
+
+  this.__cache         = {};
+
+  this.__init_promise  = null;
+  this.__modules       = opts.modules || {};
+  this.__memory        = null;
+  this.__wasm          = {};
+
+  this.__isLE = ((new Uint32Array((new Uint8Array([ 1, 0, 0, 0 ])).buffer))[0] === 1);
+
+  if (!this.options.js && !this.options.wasm) {
+    throw new Error('mathlib: at least "js" or "wasm" should be enabled');
+  }
+}
+
+
+MultiMath.prototype.has_wasm = hasWebAssembly;
+
+
+MultiMath.prototype.use = function (module) {
+  this.__modules[module.name] = module;
+
+  // Pin the best possible implementation
+  if (this.options.wasm && this.has_wasm() && module.wasm_fn) {
+    this[module.name] = module.wasm_fn;
+  } else {
+    this[module.name] = module.fn;
+  }
+
+  return this;
+};
+
+
+MultiMath.prototype.init = function () {
+  if (this.__init_promise) return this.__init_promise;
+
+  if (!this.options.js && this.options.wasm && !this.has_wasm()) {
+    return Promise.reject(new Error('mathlib: only "wasm" was enabled, but it\'s not supported'));
+  }
+
+  var self = this;
+
+  this.__init_promise = Promise.all(Object.keys(self.__modules).map(function (name) {
+    var module = self.__modules[name];
+
+    if (!self.options.wasm || !self.has_wasm() || !module.wasm_fn) return null;
+
+    // If already compiled - exit
+    if (self.__wasm[name]) return null;
+
+    // Compile wasm source
+    return WebAssembly.compile(self.__base64decode(module.wasm_src))
+      .then(function (m) { self.__wasm[name] = m; });
+  }))
+    .then(function () { return self; });
+
+  return this.__init_promise;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Methods below are for internal use from plugins
+
+
+// Simple decode base64 to typed array. Useful to load embedded webassembly
+// code. You probably don't need to call this method directly.
+//
+MultiMath.prototype.__base64decode = base64decode;
+
+
+// Increase current memory to include specified number of bytes. Do nothing if
+// size is already ok. You probably don't need to call this method directly,
+// because it will be invoked from `.__instance()`.
+//
+MultiMath.prototype.__reallocate = function mem_grow_to(bytes) {
+  if (!this.__memory) {
+    this.__memory = new WebAssembly.Memory({
+      initial: Math.ceil(bytes / (64 * 1024))
+    });
+    return this.__memory;
+  }
+
+  var mem_size = this.__memory.buffer.byteLength;
+
+  if (mem_size < bytes) {
+    this.__memory.grow(Math.ceil((bytes - mem_size) / (64 * 1024)));
+  }
+
+  return this.__memory;
+};
+
+
+// Returns instantinated webassembly item by name, with specified memory size
+// and environment.
+// - use cache if available
+// - do sync module init, if async init was not called earlier
+// - allocate memory if not enougth
+// - can export functions to webassembly via "env_extra",
+//   for example, { exp: Math.exp }
+//
+MultiMath.prototype.__instance = function instance(name, memsize, env_extra) {
+  if (memsize) this.__reallocate(memsize);
+
+  // If .init() was not called, do sync compile
+  if (!this.__wasm[name]) {
+    var module = this.__modules[name];
+    this.__wasm[name] = new WebAssembly.Module(this.__base64decode(module.wasm_src));
+  }
+
+  if (!this.__cache[name]) {
+    var env_base = {
+      memoryBase: 0,
+      memory: this.__memory,
+      tableBase: 0,
+      table: new WebAssembly.Table({ initial: 0, element: 'anyfunc' })
+    };
+
+    this.__cache[name] = new WebAssembly.Instance(this.__wasm[name], {
+      env: assign(env_base, env_extra || {})
+    });
+  }
+
+  return this.__cache[name];
+};
+
+
+// Helper to calculate memory aligh for pointers. Webassembly does not require
+// this, but you may wish to experiment. Default base = 8;
+//
+MultiMath.prototype.__align = function align(number, base) {
+  base = base || 8;
+  var reminder = number % base;
+  return number + (reminder ? base - reminder : 0);
+};
+
+
+module.exports = MultiMath;
+
+},{"./lib/base64decode":17,"./lib/wa_detect":23,"object-assign":24}],17:[function(require,module,exports){
+// base64 decode str -> Uint8Array, to load WA modules
+//
+'use strict';
+
+
+var BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+
+
+module.exports = function base64decode(str) {
+  var input = str.replace(/[\r\n=]/g, ''), // remove CR/LF & padding to simplify scan
+      max   = input.length;
+
+  var out = new Uint8Array((max * 3) >> 2);
+
+  // Collect by 6*4 bits (3 bytes)
+
+  var bits = 0;
+  var ptr  = 0;
+
+  for (var idx = 0; idx < max; idx++) {
+    if ((idx % 4 === 0) && idx) {
+      out[ptr++] = (bits >> 16) & 0xFF;
+      out[ptr++] = (bits >> 8) & 0xFF;
+      out[ptr++] = bits & 0xFF;
+    }
+
+    bits = (bits << 6) | BASE64_MAP.indexOf(input.charAt(idx));
+  }
+
+  // Dump tail
+
+  var tailbits = (max % 4) * 6;
+
+  if (tailbits === 0) {
+    out[ptr++] = (bits >> 16) & 0xFF;
+    out[ptr++] = (bits >> 8) & 0xFF;
+    out[ptr++] = bits & 0xFF;
+  } else if (tailbits === 18) {
+    out[ptr++] = (bits >> 10) & 0xFF;
+    out[ptr++] = (bits >> 2) & 0xFF;
+  } else if (tailbits === 12) {
+    out[ptr++] = (bits >> 4) & 0xFF;
+  }
+
+  return out;
+};
+
+},{}],18:[function(require,module,exports){
+// Calculates 16-bit precision HSL lightness from 8-bit rgba buffer
+//
+'use strict';
+
+
+module.exports = function hsl_l16_js(img, width, height) {
+  var size = width * height;
+  var out = new Uint16Array(size);
+  var r, g, b, min, max;
+  for (var i = 0; i < size; i++) {
+    r = img[4 * i];
+    g = img[4 * i + 1];
+    b = img[4 * i + 2];
+    max = (r >= g && r >= b) ? r : (g >= b && g >= r) ? g : b;
+    min = (r <= g && r <= b) ? r : (g <= b && g <= r) ? g : b;
+    out[i] = (max + min) * 257 >> 1;
+  }
+  return out;
+};
+
+},{}],19:[function(require,module,exports){
+'use strict';
+
+module.exports = {
+  name:     'unsharp_mask',
+  fn:       require('./unsharp_mask'),
+  wasm_fn:  require('./unsharp_mask_wasm'),
+  wasm_src: require('./unsharp_mask_wasm_base64')
+};
+
+},{"./unsharp_mask":20,"./unsharp_mask_wasm":21,"./unsharp_mask_wasm_base64":22}],20:[function(require,module,exports){
 // Unsharp mask filter
 //
 // http://stackoverflow.com/a/23322820/1031804
@@ -1261,963 +1246,963 @@ THE SOFTWARE. */
 // Image is converted from RGB to HSL, unsharp mask is applied to the
 // lightness channel and then image is converted back to RGB.
 //
-               'use strict';
-               
-               
-               var glur_mono16 = require('glur/mono16');
-               var hsl_l16     = require('./hsl_l16');
-               
-               
-               module.exports = function unsharp(img, width, height, amount, radius, threshold) {
-                       var r, g, b;
-                       var h, s, l;
-                       var min, max;
-                       var m1, m2, hShifted;
-                       var diff, iTimes4;
-                       
-                       if (amount === 0 || radius < 0.5) {
-                               return;
-                       }
-                       if (radius > 2.0) {
-                               radius = 2.0;
-                       }
-                       
-                       var lightness = hsl_l16(img, width, height);
-                       
-                       var blured = new Uint16Array(lightness); // copy, because blur modify src
-                       
-                       glur_mono16(blured, width, height, radius);
-                       
-                       var amountFp = (amount / 100 * 0x1000 + 0.5)|0;
-                       var thresholdFp = (threshold * 257)|0;
-                       
-                       var size = width * height;
-                       
-                       /* eslint-disable indent */
-                       for (var i = 0; i < size; i++) {
-                               diff = 2 * (lightness[i] - blured[i]);
-                               
-                               if (Math.abs(diff) >= thresholdFp) {
-                                       iTimes4 = i * 4;
-                                       r = img[iTimes4];
-                                       g = img[iTimes4 + 1];
-                                       b = img[iTimes4 + 2];
-                                       
-                                       // convert RGB to HSL
-                                       // take RGB, 8-bit unsigned integer per each channel
-                                       // save HSL, H and L are 16-bit unsigned integers, S is 12-bit unsigned integer
-                                       // math is taken from here: http://www.easyrgb.com/index.php?X=MATH&H=18
-                                       // and adopted to be integer (fixed point in fact) for sake of performance
-                                       max = (r >= g && r >= b) ? r : (g >= r && g >= b) ? g : b; // min and max are in [0..0xff]
-                                       min = (r <= g && r <= b) ? r : (g <= r && g <= b) ? g : b;
-                                       l = (max + min) * 257 >> 1; // l is in [0..0xffff] that is caused by multiplication by 257
-                                       
-                                       if (min === max) {
-                                               h = s = 0;
-                                       } else {
-                                               s = (l <= 0x7fff) ?
-                                                       (((max - min) * 0xfff) / (max + min))|0 :
-                                                       (((max - min) * 0xfff) / (2 * 0xff - max - min))|0; // s is in [0..0xfff]
-                                               // h could be less 0, it will be fixed in backward conversion to RGB, |h| <= 0xffff / 6
-                                               h = (r === max) ? (((g - b) * 0xffff) / (6 * (max - min)))|0
-                                                       : (g === max) ? 0x5555 + ((((b - r) * 0xffff) / (6 * (max - min)))|0) // 0x5555 == 0xffff / 3
-                                                               : 0xaaaa + ((((r - g) * 0xffff) / (6 * (max - min)))|0); // 0xaaaa == 0xffff * 2 / 3
-                                       }
-                                       
-                                       // add unsharp mask mask to the lightness channel
-                                       l += (amountFp * diff + 0x800) >> 12;
-                                       if (l > 0xffff) {
-                                               l = 0xffff;
-                                       } else if (l < 0) {
-                                               l = 0;
-                                       }
-                                       
-                                       // convert HSL back to RGB
-                                       // for information about math look above
-                                       if (s === 0) {
-                                               r = g = b = l >> 8;
-                                       } else {
-                                               m2 = (l <= 0x7fff) ? (l * (0x1000 + s) + 0x800) >> 12 :
-                                                       l  + (((0xffff - l) * s + 0x800) >>  12);
-                                               m1 = 2 * l - m2 >> 8;
-                                               m2 >>= 8;
-                                               // save result to RGB channels
-                                               // R channel
-                                               hShifted = (h + 0x5555) & 0xffff; // 0x5555 == 0xffff / 3
-                                               r = (hShifted >= 0xaaaa) ? m1 // 0xaaaa == 0xffff * 2 / 3
-                                                       : (hShifted >= 0x7fff) ?  m1 + ((m2 - m1) * 6 * (0xaaaa - hShifted) + 0x8000 >> 16)
-                                                               : (hShifted >= 0x2aaa) ? m2 // 0x2aaa == 0xffff / 6
-                                                                       : m1 + ((m2 - m1) * 6 * hShifted + 0x8000 >> 16);
-                                               // G channel
-                                               hShifted = h & 0xffff;
-                                               g = (hShifted >= 0xaaaa) ? m1 // 0xaaaa == 0xffff * 2 / 3
-                                                       : (hShifted >= 0x7fff) ?  m1 + ((m2 - m1) * 6 * (0xaaaa - hShifted) + 0x8000 >> 16)
-                                                               : (hShifted >= 0x2aaa) ? m2 // 0x2aaa == 0xffff / 6
-                                                                       : m1 + ((m2 - m1) * 6 * hShifted + 0x8000 >> 16);
-                                               // B channel
-                                               hShifted = (h - 0x5555) & 0xffff;
-                                               b = (hShifted >= 0xaaaa) ? m1 // 0xaaaa == 0xffff * 2 / 3
-                                                       : (hShifted >= 0x7fff) ?  m1 + ((m2 - m1) * 6 * (0xaaaa - hShifted) + 0x8000 >> 16)
-                                                               : (hShifted >= 0x2aaa) ? m2 // 0x2aaa == 0xffff / 6
-                                                                       : m1 + ((m2 - m1) * 6 * hShifted + 0x8000 >> 16);
-                                       }
-                                       
-                                       img[iTimes4] = r;
-                                       img[iTimes4 + 1] = g;
-                                       img[iTimes4 + 2] = b;
-                               }
-                       }
-               };
-               
-       },{"./hsl_l16":18,"glur/mono16":14}],21:[function(require,module,exports){
-               'use strict';
-               
-               
-               module.exports = function unsharp(img, width, height, amount, radius, threshold) {
-                       if (amount === 0 || radius < 0.5) {
-                               return;
-                       }
-                       
-                       if (radius > 2.0) {
-                               radius = 2.0;
-                       }
-                       
-                       var pixels = width * height;
-                       
-                       var img_bytes_cnt        = pixels * 4;
-                       var hsl_bytes_cnt        = pixels * 2;
-                       var blur_bytes_cnt       = pixels * 2;
-                       var blur_line_byte_cnt   = Math.max(width, height) * 4; // float32 array
-                       var blur_coeffs_byte_cnt = 8 * 4; // float32 array
-                       
-                       var img_offset         = 0;
-                       var hsl_offset         = img_bytes_cnt;
-                       var blur_offset        = hsl_offset + hsl_bytes_cnt;
-                       var blur_tmp_offset    = blur_offset + blur_bytes_cnt;
-                       var blur_line_offset   = blur_tmp_offset + blur_bytes_cnt;
-                       var blur_coeffs_offset = blur_line_offset + blur_line_byte_cnt;
-                       
-                       var instance = this.__instance(
-                               'unsharp_mask',
-                               img_bytes_cnt + hsl_bytes_cnt + blur_bytes_cnt * 2 + blur_line_byte_cnt + blur_coeffs_byte_cnt,
-                               { exp: Math.exp }
-                       );
-                       
-                       // 32-bit copy is much faster in chrome
-                       var img32 = new Uint32Array(img.buffer);
-                       var mem32 = new Uint32Array(this.__memory.buffer);
-                       mem32.set(img32);
-                       
-                       // HSL
-                       var fn = instance.exports.hsl_l16 || instance.exports._hsl_l16;
-                       fn(img_offset, hsl_offset, width, height);
-                       
-                       // BLUR
-                       fn = instance.exports.blurMono16 || instance.exports._blurMono16;
-                       fn(hsl_offset, blur_offset, blur_tmp_offset,
-                               blur_line_offset, blur_coeffs_offset, width, height, radius);
-                       
-                       // UNSHARP
-                       fn = instance.exports.unsharp || instance.exports._unsharp;
-                       fn(img_offset, img_offset, hsl_offset,
-                               blur_offset, width, height, amount, threshold);
-                       
-                       // 32-bit copy is much faster in chrome
-                       img32.set(new Uint32Array(this.__memory.buffer, 0, pixels));
-               };
-               
-       },{}],22:[function(require,module,exports){
+'use strict';
+
+
+var glur_mono16 = require('glur/mono16');
+var hsl_l16     = require('./hsl_l16');
+
+
+module.exports = function unsharp(img, width, height, amount, radius, threshold) {
+  var r, g, b;
+  var h, s, l;
+  var min, max;
+  var m1, m2, hShifted;
+  var diff, iTimes4;
+
+  if (amount === 0 || radius < 0.5) {
+    return;
+  }
+  if (radius > 2.0) {
+    radius = 2.0;
+  }
+
+  var lightness = hsl_l16(img, width, height);
+
+  var blured = new Uint16Array(lightness); // copy, because blur modify src
+
+  glur_mono16(blured, width, height, radius);
+
+  var amountFp = (amount / 100 * 0x1000 + 0.5)|0;
+  var thresholdFp = (threshold * 257)|0;
+
+  var size = width * height;
+
+  /* eslint-disable indent */
+  for (var i = 0; i < size; i++) {
+    diff = 2 * (lightness[i] - blured[i]);
+
+    if (Math.abs(diff) >= thresholdFp) {
+      iTimes4 = i * 4;
+      r = img[iTimes4];
+      g = img[iTimes4 + 1];
+      b = img[iTimes4 + 2];
+
+      // convert RGB to HSL
+      // take RGB, 8-bit unsigned integer per each channel
+      // save HSL, H and L are 16-bit unsigned integers, S is 12-bit unsigned integer
+      // math is taken from here: http://www.easyrgb.com/index.php?X=MATH&H=18
+      // and adopted to be integer (fixed point in fact) for sake of performance
+      max = (r >= g && r >= b) ? r : (g >= r && g >= b) ? g : b; // min and max are in [0..0xff]
+      min = (r <= g && r <= b) ? r : (g <= r && g <= b) ? g : b;
+      l = (max + min) * 257 >> 1; // l is in [0..0xffff] that is caused by multiplication by 257
+
+      if (min === max) {
+        h = s = 0;
+      } else {
+        s = (l <= 0x7fff) ?
+          (((max - min) * 0xfff) / (max + min))|0 :
+          (((max - min) * 0xfff) / (2 * 0xff - max - min))|0; // s is in [0..0xfff]
+        // h could be less 0, it will be fixed in backward conversion to RGB, |h| <= 0xffff / 6
+        h = (r === max) ? (((g - b) * 0xffff) / (6 * (max - min)))|0
+          : (g === max) ? 0x5555 + ((((b - r) * 0xffff) / (6 * (max - min)))|0) // 0x5555 == 0xffff / 3
+          : 0xaaaa + ((((r - g) * 0xffff) / (6 * (max - min)))|0); // 0xaaaa == 0xffff * 2 / 3
+      }
+
+      // add unsharp mask mask to the lightness channel
+      l += (amountFp * diff + 0x800) >> 12;
+      if (l > 0xffff) {
+        l = 0xffff;
+      } else if (l < 0) {
+        l = 0;
+      }
+
+      // convert HSL back to RGB
+      // for information about math look above
+      if (s === 0) {
+        r = g = b = l >> 8;
+      } else {
+        m2 = (l <= 0x7fff) ? (l * (0x1000 + s) + 0x800) >> 12 :
+          l  + (((0xffff - l) * s + 0x800) >>  12);
+        m1 = 2 * l - m2 >> 8;
+        m2 >>= 8;
+        // save result to RGB channels
+        // R channel
+        hShifted = (h + 0x5555) & 0xffff; // 0x5555 == 0xffff / 3
+        r = (hShifted >= 0xaaaa) ? m1 // 0xaaaa == 0xffff * 2 / 3
+          : (hShifted >= 0x7fff) ?  m1 + ((m2 - m1) * 6 * (0xaaaa - hShifted) + 0x8000 >> 16)
+          : (hShifted >= 0x2aaa) ? m2 // 0x2aaa == 0xffff / 6
+          : m1 + ((m2 - m1) * 6 * hShifted + 0x8000 >> 16);
+        // G channel
+        hShifted = h & 0xffff;
+        g = (hShifted >= 0xaaaa) ? m1 // 0xaaaa == 0xffff * 2 / 3
+          : (hShifted >= 0x7fff) ?  m1 + ((m2 - m1) * 6 * (0xaaaa - hShifted) + 0x8000 >> 16)
+          : (hShifted >= 0x2aaa) ? m2 // 0x2aaa == 0xffff / 6
+          : m1 + ((m2 - m1) * 6 * hShifted + 0x8000 >> 16);
+        // B channel
+        hShifted = (h - 0x5555) & 0xffff;
+        b = (hShifted >= 0xaaaa) ? m1 // 0xaaaa == 0xffff * 2 / 3
+          : (hShifted >= 0x7fff) ?  m1 + ((m2 - m1) * 6 * (0xaaaa - hShifted) + 0x8000 >> 16)
+          : (hShifted >= 0x2aaa) ? m2 // 0x2aaa == 0xffff / 6
+          : m1 + ((m2 - m1) * 6 * hShifted + 0x8000 >> 16);
+      }
+
+      img[iTimes4] = r;
+      img[iTimes4 + 1] = g;
+      img[iTimes4 + 2] = b;
+    }
+  }
+};
+
+},{"./hsl_l16":18,"glur/mono16":14}],21:[function(require,module,exports){
+'use strict';
+
+
+module.exports = function unsharp(img, width, height, amount, radius, threshold) {
+  if (amount === 0 || radius < 0.5) {
+    return;
+  }
+
+  if (radius > 2.0) {
+    radius = 2.0;
+  }
+
+  var pixels = width * height;
+
+  var img_bytes_cnt        = pixels * 4;
+  var hsl_bytes_cnt        = pixels * 2;
+  var blur_bytes_cnt       = pixels * 2;
+  var blur_line_byte_cnt   = Math.max(width, height) * 4; // float32 array
+  var blur_coeffs_byte_cnt = 8 * 4; // float32 array
+
+  var img_offset         = 0;
+  var hsl_offset         = img_bytes_cnt;
+  var blur_offset        = hsl_offset + hsl_bytes_cnt;
+  var blur_tmp_offset    = blur_offset + blur_bytes_cnt;
+  var blur_line_offset   = blur_tmp_offset + blur_bytes_cnt;
+  var blur_coeffs_offset = blur_line_offset + blur_line_byte_cnt;
+
+  var instance = this.__instance(
+    'unsharp_mask',
+    img_bytes_cnt + hsl_bytes_cnt + blur_bytes_cnt * 2 + blur_line_byte_cnt + blur_coeffs_byte_cnt,
+    { exp: Math.exp }
+  );
+
+  // 32-bit copy is much faster in chrome
+  var img32 = new Uint32Array(img.buffer);
+  var mem32 = new Uint32Array(this.__memory.buffer);
+  mem32.set(img32);
+
+  // HSL
+  var fn = instance.exports.hsl_l16 || instance.exports._hsl_l16;
+  fn(img_offset, hsl_offset, width, height);
+
+  // BLUR
+  fn = instance.exports.blurMono16 || instance.exports._blurMono16;
+  fn(hsl_offset, blur_offset, blur_tmp_offset,
+    blur_line_offset, blur_coeffs_offset, width, height, radius);
+
+  // UNSHARP
+  fn = instance.exports.unsharp || instance.exports._unsharp;
+  fn(img_offset, img_offset, hsl_offset,
+    blur_offset, width, height, amount, threshold);
+
+  // 32-bit copy is much faster in chrome
+  img32.set(new Uint32Array(this.__memory.buffer, 0, pixels));
+};
+
+},{}],22:[function(require,module,exports){
 // This is autogenerated file from math.wasm, don't edit.
 //
-               'use strict';
-               
-               /* eslint-disable max-len */
-               module.exports = 'AGFzbQEAAAABMQZgAXwBfGACfX8AYAZ/f39/f38AYAh/f39/f39/fQBgBH9/f38AYAh/f39/f39/fwACGQIDZW52A2V4cAAAA2VudgZtZW1vcnkCAAEDBgUBAgMEBQQEAXAAAAdMBRZfX2J1aWxkX2dhdXNzaWFuX2NvZWZzAAEOX19nYXVzczE2X2xpbmUAAgpibHVyTW9ubzE2AAMHaHNsX2wxNgAEB3Vuc2hhcnAABQkBAAqJEAXZAQEGfAJAIAFE24a6Q4Ia+z8gALujIgOaEAAiBCAEoCIGtjgCECABIANEAAAAAAAAAMCiEAAiBbaMOAIUIAFEAAAAAAAA8D8gBKEiAiACoiAEIAMgA6CiRAAAAAAAAPA/oCAFoaMiArY4AgAgASAEIANEAAAAAAAA8L+gIAKioiIHtjgCBCABIAQgA0QAAAAAAADwP6AgAqKiIgO2OAIIIAEgBSACoiIEtow4AgwgASACIAegIAVEAAAAAAAA8D8gBqGgIgKjtjgCGCABIAMgBKEgAqO2OAIcCwu3AwMDfwR9CHwCQCADKgIUIQkgAyoCECEKIAMqAgwhCyADKgIIIQwCQCAEQX9qIgdBAEgiCA0AIAIgAC8BALgiDSADKgIYu6IiDiAJuyIQoiAOIAq7IhGiIA0gAyoCBLsiEqIgAyoCALsiEyANoqCgoCIPtjgCACACQQRqIQIgAEECaiEAIAdFDQAgBCEGA0AgAiAOIBCiIA8iDiARoiANIBKiIBMgAC8BALgiDaKgoKAiD7Y4AgAgAkEEaiECIABBAmohACAGQX9qIgZBAUoNAAsLAkAgCA0AIAEgByAFbEEBdGogAEF+ai8BACIIuCINIAu7IhGiIA0gDLsiEqKgIA0gAyoCHLuiIg4gCrsiE6KgIA4gCbsiFKKgIg8gAkF8aioCALugqzsBACAHRQ0AIAJBeGohAiAAQXxqIQBBACAFQQF0ayEHIAEgBSAEQQF0QXxqbGohBgNAIAghAyAALwEAIQggBiANIBGiIAO4Ig0gEqKgIA8iECAToqAgDiAUoqAiDyACKgIAu6CrOwEAIAYgB2ohBiAAQX5qIQAgAkF8aiECIBAhDiAEQX9qIgRBAUoNAAsLCwvfAgIDfwZ8AkAgB0MAAAAAWw0AIARE24a6Q4Ia+z8gB0MAAAA/l7ujIgyaEAAiDSANoCIPtjgCECAEIAxEAAAAAAAAAMCiEAAiDraMOAIUIAREAAAAAAAA8D8gDaEiCyALoiANIAwgDKCiRAAAAAAAAPA/oCAOoaMiC7Y4AgAgBCANIAxEAAAAAAAA8L+gIAuioiIQtjgCBCAEIA0gDEQAAAAAAADwP6AgC6KiIgy2OAIIIAQgDiALoiINtow4AgwgBCALIBCgIA5EAAAAAAAA8D8gD6GgIgujtjgCGCAEIAwgDaEgC6O2OAIcIAYEQCAFQQF0IQogBiEJIAIhCANAIAAgCCADIAQgBSAGEAIgACAKaiEAIAhBAmohCCAJQX9qIgkNAAsLIAVFDQAgBkEBdCEIIAUhAANAIAIgASADIAQgBiAFEAIgAiAIaiECIAFBAmohASAAQX9qIgANAAsLC7wBAQV/IAMgAmwiAwRAQQAgA2shBgNAIAAoAgAiBEEIdiIHQf8BcSECAn8gBEH/AXEiAyAEQRB2IgRB/wFxIgVPBEAgAyIIIAMgAk8NARoLIAQgBCAHIAIgA0kbIAIgBUkbQf8BcQshCAJAIAMgAk0EQCADIAVNDQELIAQgByAEIAMgAk8bIAIgBUsbQf8BcSEDCyAAQQRqIQAgASADIAhqQYECbEEBdjsBACABQQJqIQEgBkEBaiIGDQALCwvTBgEKfwJAIAazQwAAgEWUQwAAyEKVu0QAAAAAAADgP6CqIQ0gBSAEbCILBEAgB0GBAmwhDgNAQQAgAi8BACADLwEAayIGQQF0IgdrIAcgBkEASBsgDk8EQCAAQQJqLQAAIQUCfyAALQAAIgYgAEEBai0AACIESSIJRQRAIAYiCCAGIAVPDQEaCyAFIAUgBCAEIAVJGyAGIARLGwshCAJ/IAYgBE0EQCAGIgogBiAFTQ0BGgsgBSAFIAQgBCAFSxsgCRsLIgogCGoiD0GBAmwiEEEBdiERQQAhDAJ/QQAiCSAIIApGDQAaIAggCmsiCUH/H2wgD0H+AyAIayAKayAQQYCABEkbbSEMIAYgCEYEQCAEIAVrQf//A2wgCUEGbG0MAQsgBSAGayAGIARrIAQgCEYiBhtB//8DbCAJQQZsbUHVqgFBqtUCIAYbagshCSARIAcgDWxBgBBqQQx1aiIGQQAgBkEAShsiBkH//wMgBkH//wNIGyEGAkACfwJAIAxB//8DcSIFBEAgBkH//wFKDQEgBUGAIGogBmxBgBBqQQx2DAILIAZBCHYiBiEFIAYhBAwCCyAFIAZB//8Dc2xBgBBqQQx2IAZqCyIFQQh2IQcgBkEBdCAFa0EIdiIGIQQCQCAJQdWqAWpB//8DcSIFQanVAksNACAFQf//AU8EQEGq1QIgBWsgByAGa2xBBmxBgIACakEQdiAGaiEEDAELIAchBCAFQanVAEsNACAFIAcgBmtsQQZsQYCAAmpBEHYgBmohBAsCfyAGIgUgCUH//wNxIghBqdUCSw0AGkGq1QIgCGsgByAGa2xBBmxBgIACakEQdiAGaiAIQf//AU8NABogByIFIAhBqdUASw0AGiAIIAcgBmtsQQZsQYCAAmpBEHYgBmoLIQUgCUGr1QJqQf//A3EiCEGp1QJLDQAgCEH//wFPBEBBqtUCIAhrIAcgBmtsQQZsQYCAAmpBEHYgBmohBgwBCyAIQanVAEsEQCAHIQYMAQsgCCAHIAZrbEEGbEGAgAJqQRB2IAZqIQYLIAEgBDoAACABQQFqIAU6AAAgAUECaiAGOgAACyADQQJqIQMgAkECaiECIABBBGohACABQQRqIQEgC0F/aiILDQALCwsL';
-               
-       },{}],23:[function(require,module,exports){
+'use strict';
+
+/* eslint-disable max-len */
+module.exports = 'AGFzbQEAAAABMQZgAXwBfGACfX8AYAZ/f39/f38AYAh/f39/f39/fQBgBH9/f38AYAh/f39/f39/fwACGQIDZW52A2V4cAAAA2VudgZtZW1vcnkCAAEDBgUBAgMEBQQEAXAAAAdMBRZfX2J1aWxkX2dhdXNzaWFuX2NvZWZzAAEOX19nYXVzczE2X2xpbmUAAgpibHVyTW9ubzE2AAMHaHNsX2wxNgAEB3Vuc2hhcnAABQkBAAqJEAXZAQEGfAJAIAFE24a6Q4Ia+z8gALujIgOaEAAiBCAEoCIGtjgCECABIANEAAAAAAAAAMCiEAAiBbaMOAIUIAFEAAAAAAAA8D8gBKEiAiACoiAEIAMgA6CiRAAAAAAAAPA/oCAFoaMiArY4AgAgASAEIANEAAAAAAAA8L+gIAKioiIHtjgCBCABIAQgA0QAAAAAAADwP6AgAqKiIgO2OAIIIAEgBSACoiIEtow4AgwgASACIAegIAVEAAAAAAAA8D8gBqGgIgKjtjgCGCABIAMgBKEgAqO2OAIcCwu3AwMDfwR9CHwCQCADKgIUIQkgAyoCECEKIAMqAgwhCyADKgIIIQwCQCAEQX9qIgdBAEgiCA0AIAIgAC8BALgiDSADKgIYu6IiDiAJuyIQoiAOIAq7IhGiIA0gAyoCBLsiEqIgAyoCALsiEyANoqCgoCIPtjgCACACQQRqIQIgAEECaiEAIAdFDQAgBCEGA0AgAiAOIBCiIA8iDiARoiANIBKiIBMgAC8BALgiDaKgoKAiD7Y4AgAgAkEEaiECIABBAmohACAGQX9qIgZBAUoNAAsLAkAgCA0AIAEgByAFbEEBdGogAEF+ai8BACIIuCINIAu7IhGiIA0gDLsiEqKgIA0gAyoCHLuiIg4gCrsiE6KgIA4gCbsiFKKgIg8gAkF8aioCALugqzsBACAHRQ0AIAJBeGohAiAAQXxqIQBBACAFQQF0ayEHIAEgBSAEQQF0QXxqbGohBgNAIAghAyAALwEAIQggBiANIBGiIAO4Ig0gEqKgIA8iECAToqAgDiAUoqAiDyACKgIAu6CrOwEAIAYgB2ohBiAAQX5qIQAgAkF8aiECIBAhDiAEQX9qIgRBAUoNAAsLCwvfAgIDfwZ8AkAgB0MAAAAAWw0AIARE24a6Q4Ia+z8gB0MAAAA/l7ujIgyaEAAiDSANoCIPtjgCECAEIAxEAAAAAAAAAMCiEAAiDraMOAIUIAREAAAAAAAA8D8gDaEiCyALoiANIAwgDKCiRAAAAAAAAPA/oCAOoaMiC7Y4AgAgBCANIAxEAAAAAAAA8L+gIAuioiIQtjgCBCAEIA0gDEQAAAAAAADwP6AgC6KiIgy2OAIIIAQgDiALoiINtow4AgwgBCALIBCgIA5EAAAAAAAA8D8gD6GgIgujtjgCGCAEIAwgDaEgC6O2OAIcIAYEQCAFQQF0IQogBiEJIAIhCANAIAAgCCADIAQgBSAGEAIgACAKaiEAIAhBAmohCCAJQX9qIgkNAAsLIAVFDQAgBkEBdCEIIAUhAANAIAIgASADIAQgBiAFEAIgAiAIaiECIAFBAmohASAAQX9qIgANAAsLC7wBAQV/IAMgAmwiAwRAQQAgA2shBgNAIAAoAgAiBEEIdiIHQf8BcSECAn8gBEH/AXEiAyAEQRB2IgRB/wFxIgVPBEAgAyIIIAMgAk8NARoLIAQgBCAHIAIgA0kbIAIgBUkbQf8BcQshCAJAIAMgAk0EQCADIAVNDQELIAQgByAEIAMgAk8bIAIgBUsbQf8BcSEDCyAAQQRqIQAgASADIAhqQYECbEEBdjsBACABQQJqIQEgBkEBaiIGDQALCwvTBgEKfwJAIAazQwAAgEWUQwAAyEKVu0QAAAAAAADgP6CqIQ0gBSAEbCILBEAgB0GBAmwhDgNAQQAgAi8BACADLwEAayIGQQF0IgdrIAcgBkEASBsgDk8EQCAAQQJqLQAAIQUCfyAALQAAIgYgAEEBai0AACIESSIJRQRAIAYiCCAGIAVPDQEaCyAFIAUgBCAEIAVJGyAGIARLGwshCAJ/IAYgBE0EQCAGIgogBiAFTQ0BGgsgBSAFIAQgBCAFSxsgCRsLIgogCGoiD0GBAmwiEEEBdiERQQAhDAJ/QQAiCSAIIApGDQAaIAggCmsiCUH/H2wgD0H+AyAIayAKayAQQYCABEkbbSEMIAYgCEYEQCAEIAVrQf//A2wgCUEGbG0MAQsgBSAGayAGIARrIAQgCEYiBhtB//8DbCAJQQZsbUHVqgFBqtUCIAYbagshCSARIAcgDWxBgBBqQQx1aiIGQQAgBkEAShsiBkH//wMgBkH//wNIGyEGAkACfwJAIAxB//8DcSIFBEAgBkH//wFKDQEgBUGAIGogBmxBgBBqQQx2DAILIAZBCHYiBiEFIAYhBAwCCyAFIAZB//8Dc2xBgBBqQQx2IAZqCyIFQQh2IQcgBkEBdCAFa0EIdiIGIQQCQCAJQdWqAWpB//8DcSIFQanVAksNACAFQf//AU8EQEGq1QIgBWsgByAGa2xBBmxBgIACakEQdiAGaiEEDAELIAchBCAFQanVAEsNACAFIAcgBmtsQQZsQYCAAmpBEHYgBmohBAsCfyAGIgUgCUH//wNxIghBqdUCSw0AGkGq1QIgCGsgByAGa2xBBmxBgIACakEQdiAGaiAIQf//AU8NABogByIFIAhBqdUASw0AGiAIIAcgBmtsQQZsQYCAAmpBEHYgBmoLIQUgCUGr1QJqQf//A3EiCEGp1QJLDQAgCEH//wFPBEBBqtUCIAhrIAcgBmtsQQZsQYCAAmpBEHYgBmohBgwBCyAIQanVAEsEQCAHIQYMAQsgCCAHIAZrbEEGbEGAgAJqQRB2IAZqIQYLIAEgBDoAACABQQFqIAU6AAAgAUECaiAGOgAACyADQQJqIQMgAkECaiECIABBBGohACABQQRqIQEgC0F/aiILDQALCwsL';
+
+},{}],23:[function(require,module,exports){
 // Detect WebAssembly support.
 // - Check global WebAssembly object
 // - Try to load simple module (can be disabled via CSP)
 //
-               'use strict';
-               
-               
-               var wa;
-               
-               
-               module.exports = function hasWebAssembly() {
-                       // use cache if called before;
-                       if (typeof wa !== 'undefined') return wa;
-                       
-                       wa = false;
-                       
-                       if (typeof WebAssembly === 'undefined') return wa;
-                       
-                       // If WebAssenbly is disabled, code can throw on compile
-                       try {
-                               // https://github.com/brion/min-wasm-fail/blob/master/min-wasm-fail.in.js
-                               // Additional check that WA internals are correct
-                               
-                               /* eslint-disable comma-spacing, max-len */
-                               var bin      = new Uint8Array([ 0,97,115,109,1,0,0,0,1,6,1,96,1,127,1,127,3,2,1,0,5,3,1,0,1,7,8,1,4,116,101,115,116,0,0,10,16,1,14,0,32,0,65,1,54,2,0,32,0,40,2,0,11 ]);
-                               var module   = new WebAssembly.Module(bin);
-                               var instance = new WebAssembly.Instance(module, {});
-                               
-                               // test storing to and loading from a non-zero location via a parameter.
-                               // Safari on iOS 11.2.5 returns 0 unexpectedly at non-zero locations
-                               if (instance.exports.test(4) !== 0) wa = true;
-                               
-                               return wa;
-                       } catch (__) {}
-                       
-                       return wa;
-               };
-               
-       },{}],24:[function(require,module,exports){
-               /*
-               object-assign
-               (c) Sindre Sorhus
-               @license MIT
-               */
-               
-               'use strict';
-               /* eslint-disable no-unused-vars */
-               var getOwnPropertySymbols = Object.getOwnPropertySymbols;
-               var hasOwnProperty = Object.prototype.hasOwnProperty;
-               var propIsEnumerable = Object.prototype.propertyIsEnumerable;
-               
-               function toObject(val) {
-                       if (val === null || val === undefined) {
-                               throw new TypeError('Object.assign cannot be called with null or undefined');
-                       }
-                       
-                       return Object(val);
+'use strict';
+
+
+var wa;
+
+
+module.exports = function hasWebAssembly() {
+  // use cache if called before;
+  if (typeof wa !== 'undefined') return wa;
+
+  wa = false;
+
+  if (typeof WebAssembly === 'undefined') return wa;
+
+  // If WebAssenbly is disabled, code can throw on compile
+  try {
+    // https://github.com/brion/min-wasm-fail/blob/master/min-wasm-fail.in.js
+    // Additional check that WA internals are correct
+
+    /* eslint-disable comma-spacing, max-len */
+    var bin      = new Uint8Array([ 0,97,115,109,1,0,0,0,1,6,1,96,1,127,1,127,3,2,1,0,5,3,1,0,1,7,8,1,4,116,101,115,116,0,0,10,16,1,14,0,32,0,65,1,54,2,0,32,0,40,2,0,11 ]);
+    var module   = new WebAssembly.Module(bin);
+    var instance = new WebAssembly.Instance(module, {});
+
+    // test storing to and loading from a non-zero location via a parameter.
+    // Safari on iOS 11.2.5 returns 0 unexpectedly at non-zero locations
+    if (instance.exports.test(4) !== 0) wa = true;
+
+    return wa;
+  } catch (__) {}
+
+  return wa;
+};
+
+},{}],24:[function(require,module,exports){
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/
+
+'use strict';
+/* eslint-disable no-unused-vars */
+var getOwnPropertySymbols = Object.getOwnPropertySymbols;
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+var propIsEnumerable = Object.prototype.propertyIsEnumerable;
+
+function toObject(val) {
+       if (val === null || val === undefined) {
+               throw new TypeError('Object.assign cannot be called with null or undefined');
+       }
+
+       return Object(val);
+}
+
+function shouldUseNative() {
+       try {
+               if (!Object.assign) {
+                       return false;
                }
-               
-               function shouldUseNative() {
-                       try {
-                               if (!Object.assign) {
-                                       return false;
-                               }
-                               
-                               // Detect buggy property enumeration order in older V8 versions.
-                               
-                               // https://bugs.chromium.org/p/v8/issues/detail?id=4118
-                               var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
-                               test1[5] = 'de';
-                               if (Object.getOwnPropertyNames(test1)[0] === '5') {
-                                       return false;
-                               }
-                               
-                               // https://bugs.chromium.org/p/v8/issues/detail?id=3056
-                               var test2 = {};
-                               for (var i = 0; i < 10; i++) {
-                                       test2['_' + String.fromCharCode(i)] = i;
-                               }
-                               var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
-                                       return test2[n];
-                               });
-                               if (order2.join('') !== '0123456789') {
-                                       return false;
-                               }
-                               
-                               // https://bugs.chromium.org/p/v8/issues/detail?id=3056
-                               var test3 = {};
-                               'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
-                                       test3[letter] = letter;
-                               });
-                               if (Object.keys(Object.assign({}, test3)).join('') !==
-                                       'abcdefghijklmnopqrst') {
-                                       return false;
-                               }
-                               
-                               return true;
-                       } catch (err) {
-                               // We don't expect any of the above to throw, but better to be safe.
-                               return false;
-                       }
+
+               // Detect buggy property enumeration order in older V8 versions.
+
+               // https://bugs.chromium.org/p/v8/issues/detail?id=4118
+               var test1 = new String('abc');  // eslint-disable-line no-new-wrappers
+               test1[5] = 'de';
+               if (Object.getOwnPropertyNames(test1)[0] === '5') {
+                       return false;
                }
-               
-               module.exports = shouldUseNative() ? Object.assign : function (target, source) {
-                       var from;
-                       var to = toObject(target);
-                       var symbols;
-                       
-                       for (var s = 1; s < arguments.length; s++) {
-                               from = Object(arguments[s]);
-                               
-                               for (var key in from) {
-                                       if (hasOwnProperty.call(from, key)) {
-                                               to[key] = from[key];
-                                       }
-                               }
-                               
-                               if (getOwnPropertySymbols) {
-                                       symbols = getOwnPropertySymbols(from);
-                                       for (var i = 0; i < symbols.length; i++) {
-                                               if (propIsEnumerable.call(from, symbols[i])) {
-                                                       to[symbols[i]] = from[symbols[i]];
-                                               }
-                                       }
-                               }
-                       }
-                       
-                       return to;
-               };
-               
-       },{}],25:[function(require,module,exports){
-               var bundleFn = arguments[3];
-               var sources = arguments[4];
-               var cache = arguments[5];
-               
-               var stringify = JSON.stringify;
-               
-               module.exports = function (fn, options) {
-                       var wkey;
-                       var cacheKeys = Object.keys(cache);
-                       
-                       for (var i = 0, l = cacheKeys.length; i < l; i++) {
-                               var key = cacheKeys[i];
-                               var exp = cache[key].exports;
-                               // Using babel as a transpiler to use esmodule, the export will always
-                               // be an object with the default export as a property of it. To ensure
-                               // the existing api and babel esmodule exports are both supported we
-                               // check for both
-                               if (exp === fn || exp && exp.default === fn) {
-                                       wkey = key;
-                                       break;
-                               }
-                       }
-                       
-                       if (!wkey) {
-                               wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
-                               var wcache = {};
-                               for (var i = 0, l = cacheKeys.length; i < l; i++) {
-                                       var key = cacheKeys[i];
-                                       wcache[key] = key;
-                               }
-                               sources[wkey] = [
-                                       'function(require,module,exports){' + fn + '(self); }',
-                                       wcache
-                               ];
-                       }
-                       var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
-                       
-                       var scache = {}; scache[wkey] = wkey;
-                       sources[skey] = [
-                               'function(require,module,exports){' +
-                               // try to call default if defined to also support babel esmodule exports
-                               'var f = require(' + stringify(wkey) + ');' +
-                               '(f.default ? f.default : f)(self);' +
-                               '}',
-                               scache
-                       ];
-                       
-                       var workerSources = {};
-                       resolveSources(skey);
-                       
-                       function resolveSources(key) {
-                               workerSources[key] = true;
-                               
-                               for (var depPath in sources[key][1]) {
-                                       var depKey = sources[key][1][depPath];
-                                       if (!workerSources[depKey]) {
-                                               resolveSources(depKey);
-                                       }
-                               }
-                       }
-                       
-                       var src = '(' + bundleFn + ')({'
-                               + Object.keys(workerSources).map(function (key) {
-                                       return stringify(key) + ':['
-                                               + sources[key][0]
-                                               + ',' + stringify(sources[key][1]) + ']'
-                                               ;
-                               }).join(',')
-                               + '},{},[' + stringify(skey) + '])'
-                       ;
-                       
-                       var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
-                       
-                       var blob = new Blob([src], { type: 'text/javascript' });
-                       if (options && options.bare) { return blob; }
-                       var workerUrl = URL.createObjectURL(blob);
-                       var worker = new Worker(workerUrl);
-                       worker.objectURL = workerUrl;
-                       return worker;
-               };
-               
-       },{}],"/":[function(require,module,exports){
-               'use strict';
-               
-               function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
-               
-               function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
-               
-               function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
-               
-               function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
-               
-               var assign = require('object-assign');
-               
-               var webworkify = require('webworkify');
-               
-               var MathLib = require('./lib/mathlib');
-               
-               var Pool = require('./lib/pool');
-               
-               var utils = require('./lib/utils');
-               
-               var worker = require('./lib/worker');
-               
-               var createStages = require('./lib/stepper');
-               
-               var createRegions = require('./lib/tiler'); // Deduplicate pools & limiters with the same configs
-// when user creates multiple pica instances.
-               
-               
-               var singletones = {};
-               var NEED_SAFARI_FIX = false;
-               
-               try {
-                       if (typeof navigator !== 'undefined' && navigator.userAgent) {
-                               NEED_SAFARI_FIX = navigator.userAgent.indexOf('Safari') >= 0;
-                       }
-               } catch (e) {}
-               
-               var concurrency = 1;
-               
-               if (typeof navigator !== 'undefined') {
-                       concurrency = Math.min(navigator.hardwareConcurrency || 1, 4);
+
+               // https://bugs.chromium.org/p/v8/issues/detail?id=3056
+               var test2 = {};
+               for (var i = 0; i < 10; i++) {
+                       test2['_' + String.fromCharCode(i)] = i;
                }
-               
-               var DEFAULT_PICA_OPTS = {
-                       tile: 1024,
-                       concurrency: concurrency,
-                       features: ['js', 'wasm', 'ww'],
-                       idle: 2000
-               };
-               var DEFAULT_RESIZE_OPTS = {
-                       quality: 3,
-                       alpha: false,
-                       unsharpAmount: 0,
-                       unsharpRadius: 0.0,
-                       unsharpThreshold: 0
-               };
-               var CAN_NEW_IMAGE_DATA;
-               var CAN_CREATE_IMAGE_BITMAP;
-               
-               function workerFabric() {
-                       return {
-                               value: webworkify(worker),
-                               destroy: function destroy() {
-                                       this.value.terminate();
-                                       
-                                       if (typeof window !== 'undefined') {
-                                               var url = window.URL || window.webkitURL || window.mozURL || window.msURL;
-                                               
-                                               if (url && url.revokeObjectURL && this.value.objectURL) {
-                                                       url.revokeObjectURL(this.value.objectURL);
-                                               }
-                                       }
-                               }
-                       };
-               } ////////////////////////////////////////////////////////////////////////////////
-// API methods
-               
-               
-               function Pica(options) {
-                       if (!(this instanceof Pica)) return new Pica(options);
-                       this.options = assign({}, DEFAULT_PICA_OPTS, options || {});
-                       var limiter_key = "lk_".concat(this.options.concurrency); // Share limiters to avoid multiple parallel workers when user creates
-                       // multiple pica instances.
-                       
-                       this.__limit = singletones[limiter_key] || utils.limiter(this.options.concurrency);
-                       if (!singletones[limiter_key]) singletones[limiter_key] = this.__limit; // List of supported features, according to options & browser/node.js
-                       
-                       this.features = {
-                               js: false,
-                               // pure JS implementation, can be disabled for testing
-                               wasm: false,
-                               // webassembly implementation for heavy functions
-                               cib: false,
-                               // resize via createImageBitmap (only FF at this moment)
-                               ww: false // webworkers
-                               
-                       };
-                       this.__workersPool = null; // Store requested features for webworkers
-                       
-                       this.__requested_features = [];
-                       this.__mathlib = null;
+               var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
+                       return test2[n];
+               });
+               if (order2.join('') !== '0123456789') {
+                       return false;
                }
-               
-               Pica.prototype.init = function () {
-                       var _this = this;
-                       
-                       if (this.__initPromise) return this.__initPromise; // Test if we can create ImageData without canvas and memory copy
-                       
-                       if (CAN_NEW_IMAGE_DATA !== false && CAN_NEW_IMAGE_DATA !== true) {
-                               CAN_NEW_IMAGE_DATA = false;
-                               
-                               if (typeof ImageData !== 'undefined' && typeof Uint8ClampedArray !== 'undefined') {
-                                       try {
-                                               /* eslint-disable no-new */
-                                               new ImageData(new Uint8ClampedArray(400), 10, 10);
-                                               CAN_NEW_IMAGE_DATA = true;
-                                       } catch (__) {}
-                               }
-                       } // ImageBitmap can be effective in 2 places:
-                       //
-                       // 1. Threaded jpeg unpack (basic)
-                       // 2. Built-in resize (blocked due problem in chrome, see issue #89)
-                       //
-                       // For basic use we also need ImageBitmap wo support .close() method,
-                       // see https://developer.mozilla.org/ru/docs/Web/API/ImageBitmap
-                       
-                       
-                       if (CAN_CREATE_IMAGE_BITMAP !== false && CAN_CREATE_IMAGE_BITMAP !== true) {
-                               CAN_CREATE_IMAGE_BITMAP = false;
-                               
-                               if (typeof ImageBitmap !== 'undefined') {
-                                       if (ImageBitmap.prototype && ImageBitmap.prototype.close) {
-                                               CAN_CREATE_IMAGE_BITMAP = true;
-                                       } else {
-                                               this.debug('ImageBitmap does not support .close(), disabled');
-                                       }
-                               }
-                       }
-                       
-                       var features = this.options.features.slice();
-                       
-                       if (features.indexOf('all') >= 0) {
-                               features = ['cib', 'wasm', 'js', 'ww'];
+
+               // https://bugs.chromium.org/p/v8/issues/detail?id=3056
+               var test3 = {};
+               'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
+                       test3[letter] = letter;
+               });
+               if (Object.keys(Object.assign({}, test3)).join('') !==
+                               'abcdefghijklmnopqrst') {
+                       return false;
+               }
+
+               return true;
+       } catch (err) {
+               // We don't expect any of the above to throw, but better to be safe.
+               return false;
+       }
+}
+
+module.exports = shouldUseNative() ? Object.assign : function (target, source) {
+       var from;
+       var to = toObject(target);
+       var symbols;
+
+       for (var s = 1; s < arguments.length; s++) {
+               from = Object(arguments[s]);
+
+               for (var key in from) {
+                       if (hasOwnProperty.call(from, key)) {
+                               to[key] = from[key];
                        }
-                       
-                       this.__requested_features = features;
-                       this.__mathlib = new MathLib(features); // Check WebWorker support if requested
-                       
-                       if (features.indexOf('ww') >= 0) {
-                               if (typeof window !== 'undefined' && 'Worker' in window) {
-                                       // IE <= 11 don't allow to create webworkers from string. We should check it.
-                                       // https://connect.microsoft.com/IE/feedback/details/801810/web-workers-from-blob-urls-in-ie-10-and-11
-                                       try {
-                                               var wkr = require('webworkify')(function () {});
-                                               
-                                               wkr.terminate();
-                                               this.features.ww = true; // pool uniqueness depends on pool config + webworker config
-                                               
-                                               var wpool_key = "wp_".concat(JSON.stringify(this.options));
-                                               
-                                               if (singletones[wpool_key]) {
-                                                       this.__workersPool = singletones[wpool_key];
-                                               } else {
-                                                       this.__workersPool = new Pool(workerFabric, this.options.idle);
-                                                       singletones[wpool_key] = this.__workersPool;
-                                               }
-                                       } catch (__) {}
+               }
+
+               if (getOwnPropertySymbols) {
+                       symbols = getOwnPropertySymbols(from);
+                       for (var i = 0; i < symbols.length; i++) {
+                               if (propIsEnumerable.call(from, symbols[i])) {
+                                       to[symbols[i]] = from[symbols[i]];
                                }
                        }
-                       
-                       var initMath = this.__mathlib.init().then(function (mathlib) {
-                               // Copy detected features
-                               assign(_this.features, mathlib.features);
-                       });
-                       
-                       var checkCibResize;
-                       
-                       if (!CAN_CREATE_IMAGE_BITMAP) {
-                               checkCibResize = Promise.resolve(false);
-                       } else {
-                               checkCibResize = utils.cib_support().then(function (status) {
-                                       if (_this.features.cib && features.indexOf('cib') < 0) {
-                                               _this.debug('createImageBitmap() resize supported, but disabled by config');
-                                               
-                                               return;
-                                       }
-                                       
-                                       if (features.indexOf('cib') >= 0) _this.features.cib = status;
-                               });
-                       } // Init math lib. That's async because can load some
-                       
-                       
-                       this.__initPromise = Promise.all([initMath, checkCibResize]).then(function () {
-                               return _this;
-                       });
-                       return this.__initPromise;
-               };
-               
-               Pica.prototype.resize = function (from, to, options) {
-                       var _this2 = this;
-                       
-                       this.debug('Start resize...');
-                       var opts = assign({}, DEFAULT_RESIZE_OPTS);
-                       
-                       if (!isNaN(options)) {
-                               opts = assign(opts, {
-                                       quality: options
-                               });
-                       } else if (options) {
-                               opts = assign(opts, options);
-                       }
-                       
-                       opts.toWidth = to.width;
-                       opts.toHeight = to.height;
-                       opts.width = from.naturalWidth || from.width;
-                       opts.height = from.naturalHeight || from.height; // Prevent stepper from infinite loop
-                       
-                       if (to.width === 0 || to.height === 0) {
-                               return Promise.reject(new Error("Invalid output size: ".concat(to.width, "x").concat(to.height)));
-                       }
-                       
-                       if (opts.unsharpRadius > 2) opts.unsharpRadius = 2;
-                       var canceled = false;
-                       var cancelToken = null;
-                       
-                       if (opts.cancelToken) {
-                               // Wrap cancelToken to avoid successive resolve & set flag
-                               cancelToken = opts.cancelToken.then(function (data) {
-                                       canceled = true;
-                                       throw data;
-                               }, function (err) {
-                                       canceled = true;
-                                       throw err;
-                               });
-                       }
-                       
-                       var DEST_TILE_BORDER = 3; // Max possible filter window size
-                       
-                       var destTileBorder = Math.ceil(Math.max(DEST_TILE_BORDER, 2.5 * opts.unsharpRadius | 0));
-                       return this.init().then(function () {
-                               if (canceled) return cancelToken; // if createImageBitmap supports resize, just do it and return
-                               
-                               if (_this2.features.cib) {
-                                       var toCtx = to.getContext('2d', {
-                                               alpha: Boolean(opts.alpha)
-                                       });
-                                       
-                                       _this2.debug('Resize via createImageBitmap()');
-                                       
-                                       return createImageBitmap(from, {
-                                               resizeWidth: opts.toWidth,
-                                               resizeHeight: opts.toHeight,
-                                               resizeQuality: utils.cib_quality_name(opts.quality)
-                                       }).then(function (imageBitmap) {
-                                               if (canceled) return cancelToken; // if no unsharp - draw directly to output canvas
-                                               
-                                               if (!opts.unsharpAmount) {
-                                                       toCtx.drawImage(imageBitmap, 0, 0);
-                                                       imageBitmap.close();
-                                                       toCtx = null;
-                                                       
-                                                       _this2.debug('Finished!');
-                                                       
-                                                       return to;
-                                               }
-                                               
-                                               _this2.debug('Unsharp result');
-                                               
-                                               var tmpCanvas = document.createElement('canvas');
-                                               tmpCanvas.width = opts.toWidth;
-                                               tmpCanvas.height = opts.toHeight;
-                                               var tmpCtx = tmpCanvas.getContext('2d', {
-                                                       alpha: Boolean(opts.alpha)
-                                               });
-                                               tmpCtx.drawImage(imageBitmap, 0, 0);
-                                               imageBitmap.close();
-                                               var iData = tmpCtx.getImageData(0, 0, opts.toWidth, opts.toHeight);
-                                               
-                                               _this2.__mathlib.unsharp(iData.data, opts.toWidth, opts.toHeight, opts.unsharpAmount, opts.unsharpRadius, opts.unsharpThreshold);
-                                               
-                                               toCtx.putImageData(iData, 0, 0);
-                                               iData = tmpCtx = tmpCanvas = toCtx = null;
-                                               
-                                               _this2.debug('Finished!');
-                                               
-                                               return to;
-                                       });
-                               } //
-                               // No easy way, let's resize manually via arrays
-                               //
-                               // Share cache between calls:
-                               //
-                               // - wasm instance
-                               // - wasm memory object
-                               //
-                               
-                               
-                               var cache = {}; // Call resizer in webworker or locally, depending on config
-                               
-                               var invokeResize = function invokeResize(opts) {
-                                       return Promise.resolve().then(function () {
-                                               if (!_this2.features.ww) return _this2.__mathlib.resizeAndUnsharp(opts, cache);
-                                               return new Promise(function (resolve, reject) {
-                                                       var w = _this2.__workersPool.acquire();
-                                                       
-                                                       if (cancelToken) cancelToken.catch(function (err) {
-                                                               return reject(err);
-                                                       });
-                                                       
-                                                       w.value.onmessage = function (ev) {
-                                                               w.release();
-                                                               if (ev.data.err) reject(ev.data.err);else resolve(ev.data.result);
-                                                       };
-                                                       
-                                                       w.value.postMessage({
-                                                               opts: opts,
-                                                               features: _this2.__requested_features,
-                                                               preload: {
-                                                                       wasm_nodule: _this2.__mathlib.__
-                                                               }
-                                                       }, [opts.src.buffer]);
-                                               });
-                                       });
-                               };
-                               
-                               var tileAndResize = function tileAndResize(from, to, opts) {
-                                       var srcCtx;
-                                       var srcImageBitmap;
-                                       var toCtx;
-                                       
-                                       var processTile = function processTile(tile) {
-                                               return _this2.__limit(function () {
-                                                       if (canceled) return cancelToken;
-                                                       var srcImageData; // Extract tile RGBA buffer, depending on input type
-                                                       
-                                                       if (utils.isCanvas(from)) {
-                                                               _this2.debug('Get tile pixel data'); // If input is Canvas - extract region data directly
-                                                               
-                                                               
-                                                               srcImageData = srcCtx.getImageData(tile.x, tile.y, tile.width, tile.height);
-                                                       } else {
-                                                               // If input is Image or decoded to ImageBitmap,
-                                                               // draw region to temporary canvas and extract data from it
-                                                               //
-                                                               // Note! Attempt to reuse this canvas causes significant slowdown in chrome
-                                                               //
-                                                               _this2.debug('Draw tile imageBitmap/image to temporary canvas');
-                                                               
-                                                               var tmpCanvas = document.createElement('canvas');
-                                                               tmpCanvas.width = tile.width;
-                                                               tmpCanvas.height = tile.height;
-                                                               var tmpCtx = tmpCanvas.getContext('2d', {
-                                                                       alpha: Boolean(opts.alpha)
-                                                               });
-                                                               tmpCtx.globalCompositeOperation = 'copy';
-                                                               tmpCtx.drawImage(srcImageBitmap || from, tile.x, tile.y, tile.width, tile.height, 0, 0, tile.width, tile.height);
-                                                               
-                                                               _this2.debug('Get tile pixel data');
-                                                               
-                                                               srcImageData = tmpCtx.getImageData(0, 0, tile.width, tile.height);
-                                                               tmpCtx = tmpCanvas = null;
-                                                       }
-                                                       
-                                                       var o = {
-                                                               src: srcImageData.data,
-                                                               width: tile.width,
-                                                               height: tile.height,
-                                                               toWidth: tile.toWidth,
-                                                               toHeight: tile.toHeight,
-                                                               scaleX: tile.scaleX,
-                                                               scaleY: tile.scaleY,
-                                                               offsetX: tile.offsetX,
-                                                               offsetY: tile.offsetY,
-                                                               quality: opts.quality,
-                                                               alpha: opts.alpha,
-                                                               unsharpAmount: opts.unsharpAmount,
-                                                               unsharpRadius: opts.unsharpRadius,
-                                                               unsharpThreshold: opts.unsharpThreshold
-                                                       };
-                                                       
-                                                       _this2.debug('Invoke resize math');
-                                                       
-                                                       return Promise.resolve().then(function () {
-                                                               return invokeResize(o);
-                                                       }).then(function (result) {
-                                                               if (canceled) return cancelToken;
-                                                               srcImageData = null;
-                                                               var toImageData;
-                                                               
-                                                               _this2.debug('Convert raw rgba tile result to ImageData');
-                                                               
-                                                               if (CAN_NEW_IMAGE_DATA) {
-                                                                       // this branch is for modern browsers
-                                                                       // If `new ImageData()` & Uint8ClampedArray suported
-                                                                       toImageData = new ImageData(new Uint8ClampedArray(result), tile.toWidth, tile.toHeight);
-                                                               } else {
-                                                                       // fallback for `node-canvas` and old browsers
-                                                                       // (IE11 has ImageData but does not support `new ImageData()`)
-                                                                       toImageData = toCtx.createImageData(tile.toWidth, tile.toHeight);
-                                                                       
-                                                                       if (toImageData.data.set) {
-                                                                               toImageData.data.set(result);
-                                                                       } else {
-                                                                               // IE9 don't have `.set()`
-                                                                               for (var i = toImageData.data.length - 1; i >= 0; i--) {
-                                                                                       toImageData.data[i] = result[i];
-                                                                               }
-                                                                       }
-                                                               }
-                                                               
-                                                               _this2.debug('Draw tile');
-                                                               
-                                                               if (NEED_SAFARI_FIX) {
-                                                                       // Safari draws thin white stripes between tiles without this fix
-                                                                       toCtx.putImageData(toImageData, tile.toX, tile.toY, tile.toInnerX - tile.toX, tile.toInnerY - tile.toY, tile.toInnerWidth + 1e-5, tile.toInnerHeight + 1e-5);
-                                                               } else {
-                                                                       toCtx.putImageData(toImageData, tile.toX, tile.toY, tile.toInnerX - tile.toX, tile.toInnerY - tile.toY, tile.toInnerWidth, tile.toInnerHeight);
-                                                               }
-                                                               
-                                                               return null;
-                                                       });
-                                               });
-                                       }; // Need to normalize data source first. It can be canvas or image.
-                                       // If image - try to decode in background if possible
-                                       
-                                       
-                                       return Promise.resolve().then(function () {
-                                               toCtx = to.getContext('2d', {
-                                                       alpha: Boolean(opts.alpha)
-                                               });
-                                               
-                                               if (utils.isCanvas(from)) {
-                                                       srcCtx = from.getContext('2d', {
-                                                               alpha: Boolean(opts.alpha)
-                                                       });
-                                                       return null;
-                                               }
-                                               
-                                               if (utils.isImage(from)) {
-                                                       // try do decode image in background for faster next operations
-                                                       if (!CAN_CREATE_IMAGE_BITMAP) return null;
-                                                       
-                                                       _this2.debug('Decode image via createImageBitmap');
-                                                       
-                                                       return createImageBitmap(from).then(function (imageBitmap) {
-                                                               srcImageBitmap = imageBitmap;
-                                                       });
-                                               }
-                                               
-                                               throw new Error('".from" should be image or canvas');
-                                       }).then(function () {
-                                               if (canceled) return cancelToken;
-                                               
-                                               _this2.debug('Calculate tiles'); //
-                                               // Here we are with "normalized" source,
-                                               // follow to tiling
-                                               //
-                                               
-                                               
-                                               var regions = createRegions({
-                                                       width: opts.width,
-                                                       height: opts.height,
-                                                       srcTileSize: _this2.options.tile,
-                                                       toWidth: opts.toWidth,
-                                                       toHeight: opts.toHeight,
-                                                       destTileBorder: destTileBorder
-                                               });
-                                               var jobs = regions.map(function (tile) {
-                                                       return processTile(tile);
-                                               });
-                                               
-                                               function cleanup() {
-                                                       if (srcImageBitmap) {
-                                                               srcImageBitmap.close();
-                                                               srcImageBitmap = null;
-                                                       }
-                                               }
-                                               
-                                               _this2.debug('Process tiles');
-                                               
-                                               return Promise.all(jobs).then(function () {
-                                                       _this2.debug('Finished!');
-                                                       
-                                                       cleanup();
-                                                       return to;
-                                               }, function (err) {
-                                                       cleanup();
-                                                       throw err;
-                                               });
-                                       });
-                               };
-                               
-                               var processStages = function processStages(stages, from, to, opts) {
-                                       if (canceled) return cancelToken;
-                                       
-                                       var _stages$shift = stages.shift(),
-                                               _stages$shift2 = _slicedToArray(_stages$shift, 2),
-                                               toWidth = _stages$shift2[0],
-                                               toHeight = _stages$shift2[1];
-                                       
-                                       var isLastStage = stages.length === 0;
-                                       opts = assign({}, opts, {
-                                               toWidth: toWidth,
-                                               toHeight: toHeight,
-                                               // only use user-defined quality for the last stage,
-                                               // use simpler (Hamming) filter for the first stages where
-                                               // scale factor is large enough (more than 2-3)
-                                               quality: isLastStage ? opts.quality : Math.min(1, opts.quality)
-                                       });
-                                       var tmpCanvas;
-                                       
-                                       if (!isLastStage) {
-                                               // create temporary canvas
-                                               tmpCanvas = document.createElement('canvas');
-                                               tmpCanvas.width = toWidth;
-                                               tmpCanvas.height = toHeight;
-                                       }
-                                       
-                                       return tileAndResize(from, isLastStage ? to : tmpCanvas, opts).then(function () {
-                                               if (isLastStage) return to;
-                                               opts.width = toWidth;
-                                               opts.height = toHeight;
-                                               return processStages(stages, tmpCanvas, to, opts);
-                                       });
-                               };
-                               
-                               var stages = createStages(opts.width, opts.height, opts.toWidth, opts.toHeight, _this2.options.tile, destTileBorder);
-                               return processStages(stages, from, to, opts);
-                       });
-               }; // RGBA buffer resize
+               }
+       }
+
+       return to;
+};
+
+},{}],25:[function(require,module,exports){
+var bundleFn = arguments[3];
+var sources = arguments[4];
+var cache = arguments[5];
+
+var stringify = JSON.stringify;
+
+module.exports = function (fn, options) {
+    var wkey;
+    var cacheKeys = Object.keys(cache);
+
+    for (var i = 0, l = cacheKeys.length; i < l; i++) {
+        var key = cacheKeys[i];
+        var exp = cache[key].exports;
+        // Using babel as a transpiler to use esmodule, the export will always
+        // be an object with the default export as a property of it. To ensure
+        // the existing api and babel esmodule exports are both supported we
+        // check for both
+        if (exp === fn || exp && exp.default === fn) {
+            wkey = key;
+            break;
+        }
+    }
+
+    if (!wkey) {
+        wkey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
+        var wcache = {};
+        for (var i = 0, l = cacheKeys.length; i < l; i++) {
+            var key = cacheKeys[i];
+            wcache[key] = key;
+        }
+        sources[wkey] = [
+            'function(require,module,exports){' + fn + '(self); }',
+            wcache
+        ];
+    }
+    var skey = Math.floor(Math.pow(16, 8) * Math.random()).toString(16);
+
+    var scache = {}; scache[wkey] = wkey;
+    sources[skey] = [
+        'function(require,module,exports){' +
+            // try to call default if defined to also support babel esmodule exports
+            'var f = require(' + stringify(wkey) + ');' +
+            '(f.default ? f.default : f)(self);' +
+        '}',
+        scache
+    ];
+
+    var workerSources = {};
+    resolveSources(skey);
+
+    function resolveSources(key) {
+        workerSources[key] = true;
+
+        for (var depPath in sources[key][1]) {
+            var depKey = sources[key][1][depPath];
+            if (!workerSources[depKey]) {
+                resolveSources(depKey);
+            }
+        }
+    }
+
+    var src = '(' + bundleFn + ')({'
+        + Object.keys(workerSources).map(function (key) {
+            return stringify(key) + ':['
+                + sources[key][0]
+                + ',' + stringify(sources[key][1]) + ']'
+            ;
+        }).join(',')
+        + '},{},[' + stringify(skey) + '])'
+    ;
+
+    var URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
+
+    var blob = new Blob([src], { type: 'text/javascript' });
+    if (options && options.bare) { return blob; }
+    var workerUrl = URL.createObjectURL(blob);
+    var worker = new Worker(workerUrl);
+    worker.objectURL = workerUrl;
+    return worker;
+};
+
+},{}],"/":[function(require,module,exports){
+'use strict';
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+var assign = require('object-assign');
+
+var webworkify = require('webworkify');
+
+var MathLib = require('./lib/mathlib');
+
+var Pool = require('./lib/pool');
+
+var utils = require('./lib/utils');
+
+var worker = require('./lib/worker');
+
+var createStages = require('./lib/stepper');
+
+var createRegions = require('./lib/tiler'); // Deduplicate pools & limiters with the same configs
+// when user creates multiple pica instances.
+
+
+var singletones = {};
+var NEED_SAFARI_FIX = false;
+
+try {
+  if (typeof navigator !== 'undefined' && navigator.userAgent) {
+    NEED_SAFARI_FIX = navigator.userAgent.indexOf('Safari') >= 0;
+  }
+} catch (e) {}
+
+var concurrency = 1;
+
+if (typeof navigator !== 'undefined') {
+  concurrency = Math.min(navigator.hardwareConcurrency || 1, 4);
+}
+
+var DEFAULT_PICA_OPTS = {
+  tile: 1024,
+  concurrency: concurrency,
+  features: ['js', 'wasm', 'ww'],
+  idle: 2000
+};
+var DEFAULT_RESIZE_OPTS = {
+  quality: 3,
+  alpha: false,
+  unsharpAmount: 0,
+  unsharpRadius: 0.0,
+  unsharpThreshold: 0
+};
+var CAN_NEW_IMAGE_DATA;
+var CAN_CREATE_IMAGE_BITMAP;
+
+function workerFabric() {
+  return {
+    value: webworkify(worker),
+    destroy: function destroy() {
+      this.value.terminate();
+
+      if (typeof window !== 'undefined') {
+        var url = window.URL || window.webkitURL || window.mozURL || window.msURL;
+
+        if (url && url.revokeObjectURL && this.value.objectURL) {
+          url.revokeObjectURL(this.value.objectURL);
+        }
+      }
+    }
+  };
+} ////////////////////////////////////////////////////////////////////////////////
+// API methods
+
+
+function Pica(options) {
+  if (!(this instanceof Pica)) return new Pica(options);
+  this.options = assign({}, DEFAULT_PICA_OPTS, options || {});
+  var limiter_key = "lk_".concat(this.options.concurrency); // Share limiters to avoid multiple parallel workers when user creates
+  // multiple pica instances.
+
+  this.__limit = singletones[limiter_key] || utils.limiter(this.options.concurrency);
+  if (!singletones[limiter_key]) singletones[limiter_key] = this.__limit; // List of supported features, according to options & browser/node.js
+
+  this.features = {
+    js: false,
+    // pure JS implementation, can be disabled for testing
+    wasm: false,
+    // webassembly implementation for heavy functions
+    cib: false,
+    // resize via createImageBitmap (only FF at this moment)
+    ww: false // webworkers
+
+  };
+  this.__workersPool = null; // Store requested features for webworkers
+
+  this.__requested_features = [];
+  this.__mathlib = null;
+}
+
+Pica.prototype.init = function () {
+  var _this = this;
+
+  if (this.__initPromise) return this.__initPromise; // Test if we can create ImageData without canvas and memory copy
+
+  if (CAN_NEW_IMAGE_DATA !== false && CAN_NEW_IMAGE_DATA !== true) {
+    CAN_NEW_IMAGE_DATA = false;
+
+    if (typeof ImageData !== 'undefined' && typeof Uint8ClampedArray !== 'undefined') {
+      try {
+        /* eslint-disable no-new */
+        new ImageData(new Uint8ClampedArray(400), 10, 10);
+        CAN_NEW_IMAGE_DATA = true;
+      } catch (__) {}
+    }
+  } // ImageBitmap can be effective in 2 places:
+  //
+  // 1. Threaded jpeg unpack (basic)
+  // 2. Built-in resize (blocked due problem in chrome, see issue #89)
+  //
+  // For basic use we also need ImageBitmap wo support .close() method,
+  // see https://developer.mozilla.org/ru/docs/Web/API/ImageBitmap
+
+
+  if (CAN_CREATE_IMAGE_BITMAP !== false && CAN_CREATE_IMAGE_BITMAP !== true) {
+    CAN_CREATE_IMAGE_BITMAP = false;
+
+    if (typeof ImageBitmap !== 'undefined') {
+      if (ImageBitmap.prototype && ImageBitmap.prototype.close) {
+        CAN_CREATE_IMAGE_BITMAP = true;
+      } else {
+        this.debug('ImageBitmap does not support .close(), disabled');
+      }
+    }
+  }
+
+  var features = this.options.features.slice();
+
+  if (features.indexOf('all') >= 0) {
+    features = ['cib', 'wasm', 'js', 'ww'];
+  }
+
+  this.__requested_features = features;
+  this.__mathlib = new MathLib(features); // Check WebWorker support if requested
+
+  if (features.indexOf('ww') >= 0) {
+    if (typeof window !== 'undefined' && 'Worker' in window) {
+      // IE <= 11 don't allow to create webworkers from string. We should check it.
+      // https://connect.microsoft.com/IE/feedback/details/801810/web-workers-from-blob-urls-in-ie-10-and-11
+      try {
+        var wkr = require('webworkify')(function () {});
+
+        wkr.terminate();
+        this.features.ww = true; // pool uniqueness depends on pool config + webworker config
+
+        var wpool_key = "wp_".concat(JSON.stringify(this.options));
+
+        if (singletones[wpool_key]) {
+          this.__workersPool = singletones[wpool_key];
+        } else {
+          this.__workersPool = new Pool(workerFabric, this.options.idle);
+          singletones[wpool_key] = this.__workersPool;
+        }
+      } catch (__) {}
+    }
+  }
+
+  var initMath = this.__mathlib.init().then(function (mathlib) {
+    // Copy detected features
+    assign(_this.features, mathlib.features);
+  });
+
+  var checkCibResize;
+
+  if (!CAN_CREATE_IMAGE_BITMAP) {
+    checkCibResize = Promise.resolve(false);
+  } else {
+    checkCibResize = utils.cib_support().then(function (status) {
+      if (_this.features.cib && features.indexOf('cib') < 0) {
+        _this.debug('createImageBitmap() resize supported, but disabled by config');
+
+        return;
+      }
+
+      if (features.indexOf('cib') >= 0) _this.features.cib = status;
+    });
+  } // Init math lib. That's async because can load some
+
+
+  this.__initPromise = Promise.all([initMath, checkCibResize]).then(function () {
+    return _this;
+  });
+  return this.__initPromise;
+};
+
+Pica.prototype.resize = function (from, to, options) {
+  var _this2 = this;
+
+  this.debug('Start resize...');
+  var opts = assign({}, DEFAULT_RESIZE_OPTS);
+
+  if (!isNaN(options)) {
+    opts = assign(opts, {
+      quality: options
+    });
+  } else if (options) {
+    opts = assign(opts, options);
+  }
+
+  opts.toWidth = to.width;
+  opts.toHeight = to.height;
+  opts.width = from.naturalWidth || from.width;
+  opts.height = from.naturalHeight || from.height; // Prevent stepper from infinite loop
+
+  if (to.width === 0 || to.height === 0) {
+    return Promise.reject(new Error("Invalid output size: ".concat(to.width, "x").concat(to.height)));
+  }
+
+  if (opts.unsharpRadius > 2) opts.unsharpRadius = 2;
+  var canceled = false;
+  var cancelToken = null;
+
+  if (opts.cancelToken) {
+    // Wrap cancelToken to avoid successive resolve & set flag
+    cancelToken = opts.cancelToken.then(function (data) {
+      canceled = true;
+      throw data;
+    }, function (err) {
+      canceled = true;
+      throw err;
+    });
+  }
+
+  var DEST_TILE_BORDER = 3; // Max possible filter window size
+
+  var destTileBorder = Math.ceil(Math.max(DEST_TILE_BORDER, 2.5 * opts.unsharpRadius | 0));
+  return this.init().then(function () {
+    if (canceled) return cancelToken; // if createImageBitmap supports resize, just do it and return
+
+    if (_this2.features.cib) {
+      var toCtx = to.getContext('2d', {
+        alpha: Boolean(opts.alpha)
+      });
+
+      _this2.debug('Resize via createImageBitmap()');
+
+      return createImageBitmap(from, {
+        resizeWidth: opts.toWidth,
+        resizeHeight: opts.toHeight,
+        resizeQuality: utils.cib_quality_name(opts.quality)
+      }).then(function (imageBitmap) {
+        if (canceled) return cancelToken; // if no unsharp - draw directly to output canvas
+
+        if (!opts.unsharpAmount) {
+          toCtx.drawImage(imageBitmap, 0, 0);
+          imageBitmap.close();
+          toCtx = null;
+
+          _this2.debug('Finished!');
+
+          return to;
+        }
+
+        _this2.debug('Unsharp result');
+
+        var tmpCanvas = document.createElement('canvas');
+        tmpCanvas.width = opts.toWidth;
+        tmpCanvas.height = opts.toHeight;
+        var tmpCtx = tmpCanvas.getContext('2d', {
+          alpha: Boolean(opts.alpha)
+        });
+        tmpCtx.drawImage(imageBitmap, 0, 0);
+        imageBitmap.close();
+        var iData = tmpCtx.getImageData(0, 0, opts.toWidth, opts.toHeight);
+
+        _this2.__mathlib.unsharp_mask(iData.data, opts.toWidth, opts.toHeight, opts.unsharpAmount, opts.unsharpRadius, opts.unsharpThreshold);
+
+        toCtx.putImageData(iData, 0, 0);
+        iData = tmpCtx = tmpCanvas = toCtx = null;
+
+        _this2.debug('Finished!');
+
+        return to;
+      });
+    } //
+    // No easy way, let's resize manually via arrays
+    //
+    // Share cache between calls:
+    //
+    // - wasm instance
+    // - wasm memory object
+    //
+
+
+    var cache = {}; // Call resizer in webworker or locally, depending on config
+
+    var invokeResize = function invokeResize(opts) {
+      return Promise.resolve().then(function () {
+        if (!_this2.features.ww) return _this2.__mathlib.resizeAndUnsharp(opts, cache);
+        return new Promise(function (resolve, reject) {
+          var w = _this2.__workersPool.acquire();
+
+          if (cancelToken) cancelToken["catch"](function (err) {
+            return reject(err);
+          });
+
+          w.value.onmessage = function (ev) {
+            w.release();
+            if (ev.data.err) reject(ev.data.err);else resolve(ev.data.result);
+          };
+
+          w.value.postMessage({
+            opts: opts,
+            features: _this2.__requested_features,
+            preload: {
+              wasm_nodule: _this2.__mathlib.__
+            }
+          }, [opts.src.buffer]);
+        });
+      });
+    };
+
+    var tileAndResize = function tileAndResize(from, to, opts) {
+      var srcCtx;
+      var srcImageBitmap;
+      var toCtx;
+
+      var processTile = function processTile(tile) {
+        return _this2.__limit(function () {
+          if (canceled) return cancelToken;
+          var srcImageData; // Extract tile RGBA buffer, depending on input type
+
+          if (utils.isCanvas(from)) {
+            _this2.debug('Get tile pixel data'); // If input is Canvas - extract region data directly
+
+
+            srcImageData = srcCtx.getImageData(tile.x, tile.y, tile.width, tile.height);
+          } else {
+            // If input is Image or decoded to ImageBitmap,
+            // draw region to temporary canvas and extract data from it
+            //
+            // Note! Attempt to reuse this canvas causes significant slowdown in chrome
+            //
+            _this2.debug('Draw tile imageBitmap/image to temporary canvas');
+
+            var tmpCanvas = document.createElement('canvas');
+            tmpCanvas.width = tile.width;
+            tmpCanvas.height = tile.height;
+            var tmpCtx = tmpCanvas.getContext('2d', {
+              alpha: Boolean(opts.alpha)
+            });
+            tmpCtx.globalCompositeOperation = 'copy';
+            tmpCtx.drawImage(srcImageBitmap || from, tile.x, tile.y, tile.width, tile.height, 0, 0, tile.width, tile.height);
+
+            _this2.debug('Get tile pixel data');
+
+            srcImageData = tmpCtx.getImageData(0, 0, tile.width, tile.height);
+            tmpCtx = tmpCanvas = null;
+          }
+
+          var o = {
+            src: srcImageData.data,
+            width: tile.width,
+            height: tile.height,
+            toWidth: tile.toWidth,
+            toHeight: tile.toHeight,
+            scaleX: tile.scaleX,
+            scaleY: tile.scaleY,
+            offsetX: tile.offsetX,
+            offsetY: tile.offsetY,
+            quality: opts.quality,
+            alpha: opts.alpha,
+            unsharpAmount: opts.unsharpAmount,
+            unsharpRadius: opts.unsharpRadius,
+            unsharpThreshold: opts.unsharpThreshold
+          };
+
+          _this2.debug('Invoke resize math');
+
+          return Promise.resolve().then(function () {
+            return invokeResize(o);
+          }).then(function (result) {
+            if (canceled) return cancelToken;
+            srcImageData = null;
+            var toImageData;
+
+            _this2.debug('Convert raw rgba tile result to ImageData');
+
+            if (CAN_NEW_IMAGE_DATA) {
+              // this branch is for modern browsers
+              // If `new ImageData()` & Uint8ClampedArray suported
+              toImageData = new ImageData(new Uint8ClampedArray(result), tile.toWidth, tile.toHeight);
+            } else {
+              // fallback for `node-canvas` and old browsers
+              // (IE11 has ImageData but does not support `new ImageData()`)
+              toImageData = toCtx.createImageData(tile.toWidth, tile.toHeight);
+
+              if (toImageData.data.set) {
+                toImageData.data.set(result);
+              } else {
+                // IE9 don't have `.set()`
+                for (var i = toImageData.data.length - 1; i >= 0; i--) {
+                  toImageData.data[i] = result[i];
+                }
+              }
+            }
+
+            _this2.debug('Draw tile');
+
+            if (NEED_SAFARI_FIX) {
+              // Safari draws thin white stripes between tiles without this fix
+              toCtx.putImageData(toImageData, tile.toX, tile.toY, tile.toInnerX - tile.toX, tile.toInnerY - tile.toY, tile.toInnerWidth + 1e-5, tile.toInnerHeight + 1e-5);
+            } else {
+              toCtx.putImageData(toImageData, tile.toX, tile.toY, tile.toInnerX - tile.toX, tile.toInnerY - tile.toY, tile.toInnerWidth, tile.toInnerHeight);
+            }
+
+            return null;
+          });
+        });
+      }; // Need to normalize data source first. It can be canvas or image.
+      // If image - try to decode in background if possible
+
+
+      return Promise.resolve().then(function () {
+        toCtx = to.getContext('2d', {
+          alpha: Boolean(opts.alpha)
+        });
+
+        if (utils.isCanvas(from)) {
+          srcCtx = from.getContext('2d', {
+            alpha: Boolean(opts.alpha)
+          });
+          return null;
+        }
+
+        if (utils.isImage(from)) {
+          // try do decode image in background for faster next operations
+          if (!CAN_CREATE_IMAGE_BITMAP) return null;
+
+          _this2.debug('Decode image via createImageBitmap');
+
+          return createImageBitmap(from).then(function (imageBitmap) {
+            srcImageBitmap = imageBitmap;
+          });
+        }
+
+        throw new Error('".from" should be image or canvas');
+      }).then(function () {
+        if (canceled) return cancelToken;
+
+        _this2.debug('Calculate tiles'); //
+        // Here we are with "normalized" source,
+        // follow to tiling
+        //
+
+
+        var regions = createRegions({
+          width: opts.width,
+          height: opts.height,
+          srcTileSize: _this2.options.tile,
+          toWidth: opts.toWidth,
+          toHeight: opts.toHeight,
+          destTileBorder: destTileBorder
+        });
+        var jobs = regions.map(function (tile) {
+          return processTile(tile);
+        });
+
+        function cleanup() {
+          if (srcImageBitmap) {
+            srcImageBitmap.close();
+            srcImageBitmap = null;
+          }
+        }
+
+        _this2.debug('Process tiles');
+
+        return Promise.all(jobs).then(function () {
+          _this2.debug('Finished!');
+
+          cleanup();
+          return to;
+        }, function (err) {
+          cleanup();
+          throw err;
+        });
+      });
+    };
+
+    var processStages = function processStages(stages, from, to, opts) {
+      if (canceled) return cancelToken;
+
+      var _stages$shift = stages.shift(),
+          _stages$shift2 = _slicedToArray(_stages$shift, 2),
+          toWidth = _stages$shift2[0],
+          toHeight = _stages$shift2[1];
+
+      var isLastStage = stages.length === 0;
+      opts = assign({}, opts, {
+        toWidth: toWidth,
+        toHeight: toHeight,
+        // only use user-defined quality for the last stage,
+        // use simpler (Hamming) filter for the first stages where
+        // scale factor is large enough (more than 2-3)
+        quality: isLastStage ? opts.quality : Math.min(1, opts.quality)
+      });
+      var tmpCanvas;
+
+      if (!isLastStage) {
+        // create temporary canvas
+        tmpCanvas = document.createElement('canvas');
+        tmpCanvas.width = toWidth;
+        tmpCanvas.height = toHeight;
+      }
+
+      return tileAndResize(from, isLastStage ? to : tmpCanvas, opts).then(function () {
+        if (isLastStage) return to;
+        opts.width = toWidth;
+        opts.height = toHeight;
+        return processStages(stages, tmpCanvas, to, opts);
+      });
+    };
+
+    var stages = createStages(opts.width, opts.height, opts.toWidth, opts.toHeight, _this2.options.tile, destTileBorder);
+    return processStages(stages, from, to, opts);
+  });
+}; // RGBA buffer resize
 //
-               
-               
-               Pica.prototype.resizeBuffer = function (options) {
-                       var _this3 = this;
-                       
-                       var opts = assign({}, DEFAULT_RESIZE_OPTS, options);
-                       return this.init().then(function () {
-                               return _this3.__mathlib.resizeAndUnsharp(opts);
-                       });
-               };
-               
-               Pica.prototype.toBlob = function (canvas, mimeType, quality) {
-                       mimeType = mimeType || 'image/png';
-                       return new Promise(function (resolve) {
-                               if (canvas.toBlob) {
-                                       canvas.toBlob(function (blob) {
-                                               return resolve(blob);
-                                       }, mimeType, quality);
-                                       return;
-                               } // Fallback for old browsers
-                               
-                               
-                               var asString = atob(canvas.toDataURL(mimeType, quality).split(',')[1]);
-                               var len = asString.length;
-                               var asBuffer = new Uint8Array(len);
-                               
-                               for (var i = 0; i < len; i++) {
-                                       asBuffer[i] = asString.charCodeAt(i);
-                               }
-                               
-                               resolve(new Blob([asBuffer], {
-                                       type: mimeType
-                               }));
-                       });
-               };
-               
-               Pica.prototype.debug = function () {};
-               
-               module.exports = Pica;
-               
-       },{"./lib/mathlib":1,"./lib/pool":9,"./lib/stepper":10,"./lib/tiler":11,"./lib/utils":12,"./lib/worker":13,"object-assign":24,"webworkify":25}]},{},[])("/")
+
+
+Pica.prototype.resizeBuffer = function (options) {
+  var _this3 = this;
+
+  var opts = assign({}, DEFAULT_RESIZE_OPTS, options);
+  return this.init().then(function () {
+    return _this3.__mathlib.resizeAndUnsharp(opts);
+  });
+};
+
+Pica.prototype.toBlob = function (canvas, mimeType, quality) {
+  mimeType = mimeType || 'image/png';
+  return new Promise(function (resolve) {
+    if (canvas.toBlob) {
+      canvas.toBlob(function (blob) {
+        return resolve(blob);
+      }, mimeType, quality);
+      return;
+    } // Fallback for old browsers
+
+
+    var asString = atob(canvas.toDataURL(mimeType, quality).split(',')[1]);
+    var len = asString.length;
+    var asBuffer = new Uint8Array(len);
+
+    for (var i = 0; i < len; i++) {
+      asBuffer[i] = asString.charCodeAt(i);
+    }
+
+    resolve(new Blob([asBuffer], {
+      type: mimeType
+    }));
+  });
+};
+
+Pica.prototype.debug = function () {};
+
+module.exports = Pica;
+
+},{"./lib/mathlib":1,"./lib/pool":9,"./lib/stepper":10,"./lib/tiler":11,"./lib/utils":12,"./lib/worker":13,"object-assign":24,"webworkify":25}]},{},[])("/")
 });