UNPKG

glitch-canvas

Version:

JavaScript library for applying a glitch effect to a canvas element

180 lines (152 loc) 3.95 kB
import sanitizeInput from './input/sanitizeInput'; import imageToImageData from './input/browser/fromImage'; import base64URLToImage from './output/browser/toImage'; import base64URLToImageData from './output/toImageData'; import imageDataToBase64 from './glitch/browser/imageDataToBase64'; import glitchImageData from './glitch/glitchImageData'; import objectAssign from './util/object-assign.js'; // PROMISE_POLYFILL_HERE // constructing an object that allows for a chained interface. // for example stuff like: // // glitch( params ) // .toImage( img ) // .toImageData() // // etc... export default function glitch(params) { params = sanitizeInput(params); let inputFn; let outputFn; const worker = new Worker('workers/glitchWorker.js'); const api = { getParams, getInput, getOutput }; const inputMethods = { fromImageData, fromImage }; const outputMethods = { toImage, toDataURL, toImageData }; function getParams() { return params; } function getInput() { const result = objectAssign({}, api); if (!inputFn) { objectAssign(result, inputMethods); } return result; } function getOutput() { const result = objectAssign({}, api); if (!outputFn) { objectAssign(result, outputMethods); } return result; } function noTransform(x) { return x; } function fromImage(inputOptions) { return setInput(imageToImageData, inputOptions); } function fromImageData(inputOptions) { return setInput(noTransform, inputOptions); } function toDataURL(outputOptions) { return setOutput(noTransform); } function toImage(outputOptions) { return setOutput(base64URLToImage, outputOptions, true); } function toImageData(outputOptions) { return setOutput(base64URLToImageData, outputOptions, true); } function setInput(fn, inputOptions, canResolve) { inputFn = () => { return new Promise((resolve, reject) => { if (canResolve) { fn(inputOptions, resolve, reject); } else { if (fn === noTransform) { resolve(inputOptions); } else { try { resolve(fn(inputOptions, resolve, reject)); } catch (err) { reject(err); } } } }); }; if (isReady()) { return getResult(); } else { return getOutput(); } } function setOutput(fn, outputOptions, canResolve) { outputFn = base64URL => { return new Promise((resolve, reject) => { if (canResolve) { fn(base64URL, outputOptions, resolve, reject); } else { if (fn === noTransform) { resolve(base64URL); } else { fn(base64URL, outputOptions).then(resolve, reject); } } }); }; if (isReady()) { return getResult(); } else { return getInput(); } } function isReady() { return inputFn && outputFn; } function getResult() { return new Promise((resolve, reject) => { inputFn() .then(imageData => { return glitch(imageData, params); }, reject) .then(base64URL => { outputFn(base64URL).then(resolve, reject); }, reject); }); } function glitch(imageData, params) { return new Promise((resolve, reject) => { imageDataToBase64(imageData, params.quality) .then(base64URL => { return glitchInWorker(imageData, base64URL, params); }, reject) .then(resolve, reject); }); } function glitchInWorker(imageData, base64URL, params) { return new Promise((resolve, reject) => { worker.addEventListener('message', event => { if (event.data && event.data.base64URL) { resolve(event.data.base64URL); } else { if (event.data && event.data.err) { reject(event.data.err); } else { reject(event); } } }); worker.postMessage({ params: params, base64URL: base64URL, imageData: imageData, // phantomjs tends to forget about those two // so we send them separately imageDataWidth: imageData.width, imageDataHeight: imageData.height, }); }); } return getInput(); }