lens-filter-gamma
Version:
Small library to apply a gamma filter to a image
383 lines (346 loc) • 15 kB
JavaScript
(function(global, factory) {
typeof exports === 'object' && typeof module !== 'undefined'
? (module.exports = factory())
: typeof define === 'function' && define.amd
? define(factory)
: (global.sandbox = factory());
})(this, function() {
'use strict';
var commonjsGlobal =
typeof window !== 'undefined'
? window
: typeof global !== 'undefined'
? global
: typeof self !== 'undefined'
? self
: {};
function createCommonjsModule(fn, module) {
return (
(module = { exports: {} }),
fn(module, module.exports),
module.exports
);
}
var lensCore_umd = createCommonjsModule(function(module, exports) {
(function(global, factory) {
factory();
})(commonjsGlobal, function() {
function e(e, t, n) {
e.addEventListener('message', function(r) {
var o = r.data,
a = o.id;
if ('RPC' === o.type && null != a)
if (o.method) {
var s = t[o.method];
null == s
? e.postMessage({
type: 'RPC',
id: a,
error: 'NO_SUCH_METHOD'
})
: Promise.resolve()
.then(function() {
return s.apply(null, o.params);
})
.then(function(t) {
e.postMessage({
type: 'RPC',
id: a,
result: t
});
})
.catch(function(t) {
e.postMessage({
type: 'RPC',
id: a,
error: '' + t
});
});
} else {
var i = n[a];
if (null == i) throw Error('Unknown callback ' + a);
delete n[a],
o.error ? i[1](Error(o.error)) : i[0](o.result);
}
});
}
function workerize(t, n) {
var r = this,
o = {},
a =
'__xpo' +
Math.random()
.toString()
.substring(2) +
'__';
'function' == typeof t &&
(t =
'(' +
Function.prototype.toString.call(t) +
')(' +
a +
')'),
(t =
(function(e, t, n) {
return (
(e = (e = e.replace(
/^(\s*)export\s+default\s+/m,
function(e, r) {
return (
(n.default = !0),
'' + r + t + '.default='
);
}
)).replace(
/^(\s*)export\s+((?:async\s*)?function(?:\s*\*)?|const|let|var)(\s+)([a-zA-Z$_][a-zA-Z0-9$_]*)/gm,
function(e, r, o, a, s) {
return (
(n[s] = !0),
'' +
r +
t +
'.' +
s +
'=' +
o +
a +
s
);
}
)),
'var ' + t + '={};\n' + e + '\n' + t + ';'
);
})(t, a, o) +
'\n(' +
Function.prototype.toString.call(e) +
')(self,' +
a +
',{})');
var s,
i = URL.createObjectURL(new Blob([t])),
l = new Worker(i, n),
c = l.terminate,
u = {},
p = 0;
for (s in ((l.kill = function(e) {
l.postMessage({ type: 'KILL', signal: e }),
setTimeout(l.terminate);
}),
(l.terminate = function() {
URL.revokeObjectURL(i), c.call(r);
}),
(l.call = function(e, t) {
return new Promise(function(n, r) {
var o = 'rpc' + ++p;
(u[o] = [n, r]),
l.postMessage({
type: 'RPC',
id: o,
method: e,
params: t
});
});
}),
(l.rpcMethods = {}),
e(l, l.rpcMethods, u),
(l.expose = function(e) {
l[s] = function() {
return l.call(e, [].slice.call(arguments));
};
}),
o)) {
s in l || l.expose(s);
}
return l;
}
/**
* It returns a canvas with the given width and height
* @param {Number} w - width
* @param {Number} h - height
* @returns {Object}
*/
function getCanvas(w, h) {
var canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
return canvas;
}
/**
* Given a ImageData it returns the dataURL
* @param {ImageData} imageData
* @returns {String}
*/
function convertImageDataToCanvasURL(imageData) {
var canvas = window.document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = imageData.width;
canvas.height = imageData.height;
ctx.putImageData(imageData, 0, 0);
return canvas.toDataURL();
}
/**
* Given a worker file with the transformation the work is split
* between the configured number of workers and the transformation is applied
* returning a Promise
* @param {Object} data - image data
* @param {Function} transform - transformation function
* @param {Object} options - object to be passed to the transform function
* @param {Number} nWorkers - number of workers to transform the image
* @returns {Promise}
*/
function applyFilter(_ref) {
var data = _ref.data,
transform = _ref.transform,
options = _ref.options,
nWorkers = _ref.nWorkers;
var worker = workerize(
'\n var transform = ' +
transform +
';\n\n export function execute(canvas, index, length, options) {\n canvas.data = transform({ \n data: canvas.data, \n length: length, \n options: options\n });\n\n return { result: canvas, index: index };\n }\n '
);
// Drawing the source image into the target canvas
var canvas = getCanvas(data.width, data.height);
var context = canvas.getContext('2d');
context.putImageData(data, 0, 0);
// Minimium 1 worker
nWorkers = nWorkers || 1;
// Height of the picture chunck for every worker
var blockSize = Math.floor(canvas.height / nWorkers);
return new Promise(function(resolve) {
var finished = 0;
var height = void 0;
for (var index = 0; index < nWorkers; index++) {
// In the last worker we have to make sure we process whatever is missing
height = blockSize;
if (index + 1 === nWorkers) {
height = canvas.height - blockSize * index;
}
// Getting the picture
var canvasData = context.getImageData(
0,
blockSize * index,
canvas.width,
height
);
var length = height * canvas.width * 4;
worker
.execute(canvasData, index, length, options)
.then(function(response) {
// Copying back canvas data to canvas
// If the first webworker (index 0) returns data, apply it at pixel (0, 0) onwards
// If the second webworker (index 1) returns data, apply it at pixel (0, canvas.height/4) onwards, and so on
context.putImageData(
response.result,
0,
blockSize * response.index
);
finished++;
if (finished === nWorkers) {
resolve(
context.getImageData(
0,
0,
canvas.width,
canvas.height
)
);
}
});
}
});
}
exports.getCanvas = getCanvas;
exports.convertImageDataToCanvasURL = convertImageDataToCanvasURL;
exports.applyFilter = applyFilter;
});
});
var lensCore_umd_1 = lensCore_umd.getCanvas;
var lensCore_umd_2 = lensCore_umd.convertImageDataToCanvasURL;
var lensCore_umd_3 = lensCore_umd.applyFilter;
/**
* Iterate over the array applying the gamma transformation
* @param {Object} data
* @param {Number} length
* @param {Object} options
* @param {Number} [options.adjustment]
*/
var transform = function transform(_ref) {
var data = _ref.data,
length = _ref.length,
options = _ref.options;
for (var i = 0; i < length; i += 4) {
data[i] = Math.pow(data[i] / 255, options.adjustment) * 255;
data[i + 1] = Math.pow(data[i + 1] / 255, options.adjustment) * 255;
data[i + 2] = Math.pow(data[i + 2] / 255, options.adjustment) * 255;
}
return data;
};
/**
* @param {ImageData} data - data of a image extracted from a canvas
* @param {Object} options - options to pass to the transformation function
* @param {Number} [options.adjustment] - adjustment to apply in the transformation
* @param {Number} nWorkers - number of workers
* @returns {Promise}
*/
function gamma() {
var _ref2 =
arguments.length > 0 && arguments[0] !== undefined
? arguments[0]
: {},
data = _ref2.data,
options = _ref2.options,
nWorkers = _ref2.nWorkers;
if (!data || !options || !options.adjustment) {
throw new Error('lens-filter-gamma:: invalid options provided');
}
return lensCore_umd_3({
data: data,
transform: transform,
options: options,
nWorkers: nWorkers
});
}
var src = /*#__PURE__*/ Object.freeze({
transform: transform,
default: gamma
});
var imageGamma = (src && gamma) || src;
function applyResults(selector, canvas, context, src) {
var target = document.querySelectorAll(selector)[0];
var image = document.createElement('img');
image.setAttribute(
'src',
lensCore_umd.convertImageDataToCanvasURL(src)
);
target.appendChild(image);
}
window.onload = function() {
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
var data = context.getImageData(0, 0, img.width, img.height);
imageGamma({
data: data,
options: { adjustment: 30 },
nWorkers: 4
}).then(function(results) {
applyResults('#target-1', canvas, context, results);
});
imageGamma({
data: data,
options: { adjustment: 70 },
nWorkers: 4
}).then(function(results) {
applyResults('#target-2', canvas, context, results);
});
};
img.src = 'dummy.jpg';
};
var sandbox = {};
return sandbox;
});
//# sourceMappingURL=bundle.js.map