image-blob-reduce
Version:
High quality image resize in browser for blobs (`pica` wrapper with some sugar)
1,459 lines (1,134 loc) • 117 kB
JavaScript
/*! image-blob-reduce 4.1.0 https://github.com/nodeca/image-blob-reduce @license MIT */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ImageBlobReduce = factory());
})(this, (function () { 'use strict';
function commonjsRequire (path) {
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
}
var utils$1 = {};
utils$1.assign = function assign(to) {
var from;
for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);
for (var key in from) {
if (Object.prototype.hasOwnProperty.call(from, key)) to[key] = from[key];
}
}
return to;
};
function pick(from, props) {
var to = {};
props.forEach(function (key) {
if (Object.prototype.hasOwnProperty.call(from, key)) to[key] = from[key];
});
return to;
}
function pick_pica_resize_options(from) {
return pick(from, [
'alpha',
'unsharpAmount',
'unsharpRadius',
'unsharpThreshold',
'cancelToken'
]);
}
utils$1.pick = pick;
utils$1.pick_pica_resize_options = pick_pica_resize_options;
var pica$1 = {exports: {}};
/*!
pica
https://github.com/nodeca/pica
*/
(function (module, exports) {
(function(f){{module.exports=f();}})(function(){return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof commonjsRequire&&commonjsRequire;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 commonjsRequire&&commonjsRequire,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){
var Multimath = _dereq_('multimath');
var mm_unsharp_mask = _dereq_('./mm_unsharp_mask');
var mm_resize = _dereq_('./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);
}
MathLib.prototype = Object.create(Multimath.prototype);
MathLib.prototype.constructor = MathLib;
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,"./mm_unsharp_mask":9,"multimath":19}],2:[function(_dereq_,module,exports){
//var FIXED_FRAC_BITS = 14;
function clampTo8(i) {
return i < 0 ? 0 : i > 255 ? 255 : i;
}
function clampNegative(i) {
return i >= 0 ? i : 0;
} // Convolve image data in horizontal direction. Can be used for:
//
// 1. bitmap with premultiplied alpha
// 2. bitmap without alpha (all values 255)
//
// Notes:
//
// - output is transposed
// - output resolution is ~15 bits per channel(for better precision).
//
function convolveHor(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;
} // Store 15 bits between passes for better precision
// Instead of shift to 14 (FIXED_FRAC_BITS), shift to 7 only
//
dest[destOffset + 3] = clampNegative(a >> 7);
dest[destOffset + 2] = clampNegative(b >> 7);
dest[destOffset + 1] = clampNegative(g >> 7);
dest[destOffset] = clampNegative(r >> 7);
destOffset = destOffset + srcH * 4 | 0;
}
destOffset = (srcY + 1) * 4 | 0;
srcOffset = (srcY + 1) * srcW * 4 | 0;
}
} // Supplementary method for `convolveHor()`
//
function convolveVert(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;
} // Sync with premultiplied version for exact result match
r >>= 7;
g >>= 7;
b >>= 7;
a >>= 7; // Bring this value back in range + round result.
//
dest[destOffset + 3] = clampTo8(a + (1 << 13) >> 14);
dest[destOffset + 2] = clampTo8(b + (1 << 13) >> 14);
dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14);
dest[destOffset] = clampTo8(r + (1 << 13) >> 14);
destOffset = destOffset + srcH * 4 | 0;
}
destOffset = (srcY + 1) * 4 | 0;
srcOffset = (srcY + 1) * srcW * 4 | 0;
}
} // Premultiply & convolve image data in horizontal direction. Can be used for:
//
// - Any bitmap data, extracted with `.getImageData()` method (with
// non-premultiplied alpha)
//
// For images without alpha channel this method is slower than `convolveHor()`
//
function convolveHorWithPre(src, dest, srcW, srcH, destW, filters) {
var r, g, b, a, alpha;
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.
alpha = src[srcPtr + 3];
a = a + filterVal * alpha | 0;
b = b + filterVal * src[srcPtr + 2] * alpha | 0;
g = g + filterVal * src[srcPtr + 1] * alpha | 0;
r = r + filterVal * src[srcPtr] * alpha | 0;
srcPtr = srcPtr + 4 | 0;
} // Premultiply is (* alpha / 255).
// Postpone division for better performance
b = b / 255 | 0;
g = g / 255 | 0;
r = r / 255 | 0; // Store 15 bits between passes for better precision
// Instead of shift to 14 (FIXED_FRAC_BITS), shift to 7 only
//
dest[destOffset + 3] = clampNegative(a >> 7);
dest[destOffset + 2] = clampNegative(b >> 7);
dest[destOffset + 1] = clampNegative(g >> 7);
dest[destOffset] = clampNegative(r >> 7);
destOffset = destOffset + srcH * 4 | 0;
}
destOffset = (srcY + 1) * 4 | 0;
srcOffset = (srcY + 1) * srcW * 4 | 0;
}
} // Supplementary method for `convolveHorWithPre()`
//
function convolveVertWithPre(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;
} // Downscale to leave room for un-premultiply
r >>= 7;
g >>= 7;
b >>= 7;
a >>= 7; // Un-premultiply
a = clampTo8(a + (1 << 13) >> 14);
if (a > 0) {
r = r * 255 / a | 0;
g = g * 255 / a | 0;
b = b * 255 / a | 0;
} // Bring this value back in range + round result.
// Shift value = FIXED_FRAC_BITS + 7
//
dest[destOffset + 3] = a;
dest[destOffset + 2] = clampTo8(b + (1 << 13) >> 14);
dest[destOffset + 1] = clampTo8(g + (1 << 13) >> 14);
dest[destOffset] = clampTo8(r + (1 << 13) >> 14);
destOffset = destOffset + srcH * 4 | 0;
}
destOffset = (srcY + 1) * 4 | 0;
srcOffset = (srcY + 1) * srcW * 4 | 0;
}
}
module.exports = {
convolveHor: convolveHor,
convolveVert: convolveVert,
convolveHorWithPre: convolveHorWithPre,
convolveVertWithPre: convolveVertWithPre
};
},{}],3:[function(_dereq_,module,exports){
/* eslint-disable max-len */
module.exports = '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';
},{}],4:[function(_dereq_,module,exports){
module.exports = {
name: 'resize',
fn: _dereq_('./resize'),
wasm_fn: _dereq_('./resize_wasm'),
wasm_src: _dereq_('./convolve_wasm_base64')
};
},{"./convolve_wasm_base64":3,"./resize":5,"./resize_wasm":8}],5:[function(_dereq_,module,exports){
var createFilters = _dereq_('./resize_filter_gen');
var _require = _dereq_('./convolve'),
convolveHor = _require.convolveHor,
convolveVert = _require.convolveVert,
convolveHorWithPre = _require.convolveHorWithPre,
convolveVertWithPre = _require.convolveVertWithPre;
function hasAlpha(src, width, height) {
var ptr = 3,
len = width * height * 4 | 0;
while (ptr < len) {
if (src[ptr] !== 255) return true;
ptr = ptr + 4 | 0;
}
return false;
}
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 filter = typeof options.filter === 'undefined' ? 'mks2013' : options.filter;
var filtersX = createFilters(filter, srcW, destW, scaleX, offsetX),
filtersY = createFilters(filter, srcH, destH, scaleY, offsetY);
var tmp = new Uint16Array(destW * srcH * 4); // Autodetect if alpha channel exists, and use appropriate method
if (hasAlpha(src, srcW, srcH)) {
convolveHorWithPre(src, tmp, srcW, srcH, destW, filtersX);
convolveVertWithPre(tmp, dest, srcH, destW, destH, filtersY);
} else {
convolveHor(src, tmp, srcW, srcH, destW, filtersX);
convolveVert(tmp, dest, srcH, destW, destH, filtersY);
resetAlpha(dest, destW, destH);
}
return dest;
};
},{"./convolve":2,"./resize_filter_gen":6}],6:[function(_dereq_,module,exports){
var FILTER_INFO = _dereq_('./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(filter, srcSize, destSize, scale, offset) {
var filterFunction = FILTER_INFO.filter[filter].fn;
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.filter[filter].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(_dereq_,module,exports){
var filter = {
// Nearest neibor
box: {
win: 0.5,
fn: function fn(x) {
if (x < 0) x = -x;
return x < 0.5 ? 1.0 : 0.0;
}
},
// // Hamming
hamming: {
win: 1.0,
fn: function fn(x) {
if (x < 0) x = -x;
if (x >= 1.0) {
return 0.0;
}
if (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
lanczos2: {
win: 2.0,
fn: function fn(x) {
if (x < 0) x = -x;
if (x >= 2.0) {
return 0.0;
}
if (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
lanczos3: {
win: 3.0,
fn: function fn(x) {
if (x < 0) x = -x;
if (x >= 3.0) {
return 0.0;
}
if (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);
}
},
// Magic Kernel Sharp 2013, win = 2.5
// http://johncostella.com/magic/
mks2013: {
win: 2.5,
fn: function fn(x) {
if (x < 0) x = -x;
if (x >= 2.5) {
return 0.0;
}
if (x >= 1.5) {
return -0.125 * (x - 2.5) * (x - 2.5);
}
if (x >= 0.5) {
return 0.25 * (4 * x * x - 11 * x + 7);
}
return 1.0625 - 1.75 * x * x;
}
}
};
module.exports = {
filter: filter,
// Legacy mapping
f2q: {
box: 0,
hamming: 1,
lanczos2: 2,
lanczos3: 3
},
q2f: ['box', 'hamming', 'lanczos2', 'lanczos3']
};
},{}],8:[function(_dereq_,module,exports){
var createFilters = _dereq_('./resize_filter_gen');
function hasAlpha(src, width, height) {
var ptr = 3,
len = width * height * 4 | 0;
while (ptr < len) {
if (src[ptr] !== 255) return true;
ptr = ptr + 4 | 0;
}
return false;
}
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 filter = typeof options.filter === 'undefined' ? 'mks2013' : options.filter;
var filtersX = createFilters(filter, srcW, destW, scaleX, offsetX),
filtersY = createFilters(filter, srcH, destH, scaleY, offsetY); // destination is 0 too.
var src_offset = 0;
var src_size = Math.max(src.byteLength, dest.byteLength); // buffer between convolve passes
var tmp_offset = this.__align(src_offset + src_size);
var tmp_size = srcH * destW * 4 * 2; // 2 bytes per channel
var filtersX_offset = this.__align(tmp_offset + tmp_size);
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;
if (hasAlpha(src, srcW, srcH)) {
fn(filtersX_offset, filtersY_offset, tmp_offset, srcW, srcH, destW, destH, 1);
} else {
fn(filtersX_offset, filtersY_offset, tmp_offset, srcW, srcH, destW, destH, 0);
resetAlpha(dest, 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));
return dest;
};
},{"./resize_filter_gen":6}],9:[function(_dereq_,module,exports){
module.exports = {
name: 'unsharp_mask',
fn: _dereq_('./unsharp_mask'),
wasm_fn: _dereq_('./unsharp_mask_wasm'),
wasm_src: _dereq_('./unsharp_mask_wasm_base64')
};
},{"./unsharp_mask":10,"./unsharp_mask_wasm":11,"./unsharp_mask_wasm_base64":12}],10:[function(_dereq_,module,exports){
var glur_mono16 = _dereq_('glur/mono16');
function hsv_v16(img, width, height) {
var size = width * height;
var out = new Uint16Array(size);
var r, g, b, 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;
out[i] = max << 8;
}
return out;
}
module.exports = function unsharp(img, width, height, amount, radius, threshold) {
var v1, v2, vmul;
var diff, iTimes4;
if (amount === 0 || radius < 0.5) {
return;
}
if (radius > 2.0) {
radius = 2.0;
}
var brightness = hsv_v16(img, width, height);
var blured = new Uint16Array(brightness); // copy, because blur modify src
glur_mono16(blured, width, height, radius);
var amountFp = amount / 100 * 0x1000 + 0.5 | 0;
var thresholdFp = threshold << 8;
var size = width * height;
/* eslint-disable indent */
for (var i = 0; i < size; i++) {
v1 = brightness[i];
diff = v1 - blured[i];
if (Math.abs(diff) >= thresholdFp) {
// add unsharp mask to the brightness channel
v2 = v1 + (amountFp * diff + 0x800 >> 12); // Both v1 and v2 are within [0.0 .. 255.0] (0000-FF00) range, never going into
// [255.003 .. 255.996] (FF01-FFFF). This allows to round this value as (x+.5)|0
// later without overflowing.
v2 = v2 > 0xff00 ? 0xff00 : v2;
v2 = v2 < 0x0000 ? 0x0000 : v2; // Avoid division by 0. V=0 means rgb(0,0,0), unsharp with unsharpAmount>0 cannot
// change this value (because diff between colors gets inflated), so no need to verify correctness.
v1 = v1 !== 0 ? v1 : 1; // Multiplying V in HSV model by a constant is equivalent to multiplying each component
// in RGB by the same constant (same for HSL), see also:
// https://beesbuzz.biz/code/16-hsv-color-transforms
vmul = (v2 << 12) / v1 | 0; // Result will be in [0..255] range because:
// - all numbers are positive
// - r,g,b <= (v1/256)
// - r,g,b,(v1/256),(v2/256) <= 255
// So highest this number can get is X*255/X+0.5=255.5 which is < 256 and rounds down.
iTimes4 = i * 4;
img[iTimes4] = img[iTimes4] * vmul + 0x800 >> 12; // R
img[iTimes4 + 1] = img[iTimes4 + 1] * vmul + 0x800 >> 12; // G
img[iTimes4 + 2] = img[iTimes4 + 2] * vmul + 0x800 >> 12; // B
}
}
};
},{"glur/mono16":18}],11:[function(_dereq_,module,exports){
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 hsv_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 hsv_offset = img_bytes_cnt;
var blur_offset = hsv_offset + hsv_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 + hsv_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.hsv_v16 || instance.exports._hsv_v16;
fn(img_offset, hsv_offset, width, height); // BLUR
fn = instance.exports.blurMono16 || instance.exports._blurMono16;
fn(hsv_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, hsv_offset, blur_offset, width, height, amount, threshold); // 32-bit copy is much faster in chrome
img32.set(new Uint32Array(this.__memory.buffer, 0, pixels));
};
},{}],12:[function(_dereq_,module,exports){
/* eslint-disable max-len */
module.exports = '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';
},{}],13:[function(_dereq_,module,exports){
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;
},{}],14:[function(_dereq_,module,exports){
// 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;
};
},{}],15:[function(_dereq_,module,exports){
/*
* 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;
};
},{}],16:[function(_dereq_,module,exports){
function objClass(obj) {
return Object.prototype.toString.call(obj);
}
module.exports.isCanvas = function isCanvas(element) {
var cname = objClass(element);
return cname === '[object HTMLCanvasElement]'
/* browser */
|| cname === '[object OffscreenCanvas]' || cname === '[object Canvas]'
/* node-canvas */
;
};
module.exports.isImage = function isImage(element) {
return objClass(element) === '[object HTMLImageElement]';
};
module.exports.isImageBitmap = function isImageBitmap(element) {
return objClass(element) === '[object ImageBitmap]';
};
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(createCanvas) {
return Promise.resolve().then(function () {
if (typeof createImageBitmap === 'undefined') {
return false;
}
var c = createCanvas(100, 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;
});
};
module.exports.worker_offscreen_canvas_support = function worker_offscreen_canvas_support() {
return new Promise(function (resolve, reject) {
if (typeof OffscreenCanvas === 'undefined') {
// if OffscreenCanvas is present, we assume browser supports Worker and built-in Promise as well
resolve(false);
return;
}
function workerPayload(self) {
if (typeof createImageBitmap === 'undefined') {
self.postMessage(false);
return;
}
Promise.resolve().then(function () {
var canvas = new OffscreenCanvas(10, 10); // test that 2d context can be used in worker
var ctx = canvas.getContext('2d');
ctx.rect(0, 0, 1, 1); // test that cib can be used to return image bitmap from worker
return createImageBitmap(canvas, 0, 0, 1, 1);
}).then(function () {
return self.postMessage(true);
}, function () {
return self.postMessage(false);
});
}
var code = btoa("(".concat(workerPayload.toString(), ")(self);"));
var w = new Worker("data:text/javascript;base64,".concat(code));
w.onmessage = function (ev) {
return resolve(ev.data);
};
w.onerror = reject;
}).then(function (result) {
return result;
}, function () {
return false;
});
}; // Check if canvas.getContext('2d').getImageData can be used,
// FireFox randomizes the output of that function in `privacy.resistFingerprinting` mode
module.exports.can_use_canvas = function can_use_canvas(createCanvas) {
var usable = false;
try {
var canvas = createCanvas(2, 1);
var ctx = canvas.getContext('2d');
var d = ctx.createImageData(2, 1);
d.data[0] = 12;
d.data[1] = 23;
d.data[2] = 34;
d.data[3] = 255;
d.data[4] = 45;
d.data[5] = 56;
d.data[6] = 67;
d.data[7] = 255;
ctx.putImageData(d, 0, 0);
d = null;
d = ctx.getImageData(0, 0, 2, 1);
if (d.data[0] === 12 && d.data[1] === 23 && d.data[2] === 34 && d.data[3] === 255 && d.data[4] === 45 && d.data[5] === 56 && d.data[6] === 67 && d.data[7] === 255) {
usable = true;
}
} catch (err) {}
return usable;
}; // Check if createImageBitmap(img, sx, sy, sw, sh) signature works correctly
// with JPEG images oriented with Exif;
// https://bugs.chromium.org/p/chromium/issues/detail?id=1220671
// TODO: remove after it's fixed in chrome for at least 2 releases
module.exports.cib_can_use_region = function cib_can_use_region() {
return new Promise(function (resolve) {
if (typeof createImageBitmap === 'undefined') {
resolve(false);
return;
}
var image = new Image();
image.src = 'data:image/jpeg;base64,' + '/9j/4QBiRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAYAAAEaAAUAAAABAAAASgEbAAUAA' + 'AABAAAAUgEoAAMAAAABAAIAAAITAAMAAAABAAEAAAAAAAAAAABIAAAAAQAAAEgAAAAB/9' + 'sAQwAEAwMEAwMEBAMEBQQEBQYKBwYGBgYNCQoICg8NEBAPDQ8OERMYFBESFxIODxUcFRc' + 'ZGRsbGxAUHR8dGh8YGhsa/9sAQwEEBQUGBQYMBwcMGhEPERoaGhoaGhoaGhoaGhoaGhoa' + 'GhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoa/8IAEQgAAQACAwERAAIRAQMRA' + 'f/EABQAAQAAAAAAAAAAAAAAAAAAAAf/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAA' + 'IQAxAAAAF/P//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAQUCf//EABQRAQAAAAA' + 'AAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIB' + 'AT8Bf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEABj8Cf//EABQQAQAAAAAAAAAAA' + 'AAAAAAAAAD/2gAIAQEAAT8hf//aAAwDAQACAAMAAAAQH//EABQRAQAAAAAAAAAAAAAAAA' + 'AAAAD/2gAIAQMBAT8Qf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Qf//EABQ' + 'QAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8Qf//Z';
image.onload = function () {
createImageBitmap(image, 0, 0, image.width, image.height).then(function (bitmap) {
if (bitmap.width === image.width && bitmap.height === image.height) {
resolve(true);
} else {
resolve(false);
}
}, function () {
return resolve(false);
});
};
image.onerror = function () {
return resolve(false);
};
});
};
},{}],17:[function(_dereq_,module,exports){
module.exports = function () {
var MathLib = _dereq_('./mathlib');
var mathLib;
/* eslint-disable no-undef */
onmessage = function onmessage(ev) {
var tileOpts = ev.data.opts;
if (!tileOpts.src && tileOpts.srcBitmap) {
var canvas = new OffscreenCanvas(tileOpts.width, tileOpts.height);
var ctx = canvas.getContext('2d');
ctx.drawImage(tileOpts.srcBitmap, 0, 0);
tileOpts.src = ctx.getImageData(0, 0, tileOpts.width, tileOpts.height).data;
canvas.width = canvas.height = 0;
canvas = null;
tileOpts.srcBitmap.close();
tileOpts.srcBitmap = null; // Temporary force out data to typed array, because Chrome have artefacts
// https://github.com/nodeca/pica/issues/223
// returnBitmap = true;
}
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 data = mathLib.resizeAndUnsharp(tileOpts);
{
postMessage({
data: data
}, [data.buffer]);
}
};
};
},{"./mathlib":1}],18:[function(_dereq_,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);
convolveMono16(out, src, tmp_line, coeff, height, width);
}
module.exports = blurMono16;
},{}],19:[function(_dereq_,module,exports){
var assign = _dereq_('object-assign');
var base64decode = _dereq_('./lib/base64decode');
var hasWebAssembly = _dereq_('./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] =