UNPKG

imagedata-filters

Version:
409 lines (330 loc) 11 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.imagedataFilters = factory()); }(this, (function () { 'use strict'; // according to https://drafts.fxtf.org/filter-effects/#grayscaleEquivalent function grayscale$1 (imagedata, opts) { var i = 0; var data = imagedata.data; var len = data.length; var opts = opts || {amount: 0}; var amount = +opts.amount || 0; var compleAmount = 1 - amount; var r,g,b; for (; i < len; i += 4) { r = (0.2126 + 0.7874 * compleAmount) * data[i] + (0.7152 - 0.7152 * compleAmount) * data[i + 1] + (0.0722 - 0.0722 * compleAmount) * data[i + 2]; g = (0.2126 - 0.2126 * compleAmount) * data[i] + (0.7152 + 0.2848 * compleAmount) * data[i + 1] + (0.0722 - 0.0722 * compleAmount) * data[i + 2]; b = (0.2126 - 0.2126 * compleAmount) * data[i] + (0.7152 - 0.7152 * compleAmount) * data[i + 1] + (0.0722 + 0.9278 * compleAmount) * data[i + 2]; data[i] = r; data[i + 1] = g; data[i + 2] = b; } return imagedata } // according to https://drafts.fxtf.org/filter-effects/#saturateEquivalent function saturate$1 (imagedata, opts) { var i = 0; var data = imagedata.data; var len = data.length; var opts = opts || {amount: 0}; var amount = +opts.amount || 0; var r,g,b; for (; i < len; i += 4) { r = (.213 + .787 * amount) * data[i] + (.715 - .715 * amount) * data[i + 1] + (.072 - .072 * amount) * data[i + 2]; g = (.213 - .213 * amount) * data[i] + (.715 + .285 * amount) * data[i + 1] + (.072 - .072 * amount) * data[i + 2]; b = (.213 - .213 * amount) * data[i] + (.715 - .715 * amount) * data[i + 1] + (.072 + .928 * amount) * data[i + 2]; data[i] = r; data[i + 1] = g; data[i + 2] = b; } return imagedata } // according to https://drafts.fxtf.org/filter-effects/#sepiaEquivalent // TODO function sepia$1 (imagedata, opts) { var i = 0; var data = imagedata.data; var len = data.length; var opts = opts || {amount: 0}; var amount = +opts.amount || 0; var r,g,b; var compleAmount = 1 - amount; for (; i < len; i += 4) { r = (0.393 + 0.607 * compleAmount) * data[i] + (0.769 - 0.769 * compleAmount) * data[i + 1] + (0.189 - 0.189 * compleAmount) * data[i + 2]; g = (0.349 - 0.349 * compleAmount) * data[i] + (0.684 + 0.314 * compleAmount) * data[i + 1] + (0.168 - 0.168 * compleAmount) * data[i + 2]; b = (0.272 - 0.272 * compleAmount) * data[i] + (0.534 - 0.534 * compleAmount) * data[i + 1] + (0.131 + 0.869 * compleAmount) * data[i + 2]; data[i] = r; data[i + 1] = g; data[i + 2] = b; } return imagedata } /** * according to : https://drafts.fxtf.org/filter-effects/#huerotateEquivalent & https://www.w3.org/TR/SVG11/filters.html#feColorMatrixTypeAttribute */ function hueRotate$1 (imagedata, opts) { var i = 0; var data = imagedata.data; var len = data.length; var opts = opts || {amount: 0}; var amount = +opts.amount || 0; var r,g,b; var valueMatric = hueRotateMatrix(amount); for (i; i < len; i += 4) { r = valueMatric['a00'] * data[i] + valueMatric['a01'] * data[i + 1] + valueMatric['a02'] * data[i + 2] + 0 + 0; g = valueMatric['a10'] * data[i] + valueMatric['a11'] * data[i + 1] + valueMatric['a12'] * data[i + 2] + 0 + 0; b = valueMatric['a20'] * data[i] + valueMatric['a21'] * data[i + 1] + valueMatric['a22'] * data[i + 2]; data[i] = r; data[i + 1] = g; data[i + 2] = b; } return imagedata } /** * * @param {*} value * * | a00 a01 a02 | [+0.213 +0.715 +0.072] | a10 a11 a12 | = [+0.213 +0.715 +0.072] + | a20 a21 a22 | [+0.213 +0.715 +0.072] [+0.787 -0.715 -0.072] cos(hueRotate value) * [-0.213 +0.285 -0.072] + [-0.213 -0.715 +0.928] [-0.213 -0.715+0.928] sin(hueRotate value) * [+0.143 +0.140-0.283] [-0.787 +0.715+0.072] */ function hueRotateMatrix (value) { var a00, a01, a02, a10, a11, a12, a20, a21, a22; var cosV = Math.cos(value); var sinV = Math.sin(value); a00 = .213 + cosV * .787 + sinV * (-.213); a10 = .213 + cosV * (-.213) + sinV * .143; a20 = .213 + cosV * (-.213) + sinV * (-.787); a01 = .715 + cosV * (-.715) + sinV * (-.715); a11 = .715 + cosV * (.285) + sinV * (.140); a21 = .715 + cosV * (-.715) + sinV * (.715); a02 = .072 + cosV * (-.072) + sinV * (.928); a12 = .072 + cosV * (-.072) + sinV * (-.283); a22 = .072 + cosV * (.928) + sinV * (.072); return { a00: a00, a01: a01, a02: a02, a10: a10, a11: a11, a12: a12, a20: a20, a21: a21, a22: a22 } } function blur$1 (imagedata, opts) { var i,j; var data = imagedata.data; var width = imagedata.width; var height = imagedata.height; var len = data.length; var opts = opts || {amount: 0}; var amount = Math.round(opts.amount) || 0; var dotIndex; var gaussianDot; if (!amount) { return imagedata } var weights = getWeights(amount); for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { dotIndex = i * 4 + j * 4 * width; gaussianDot = getGaussianDot(i, j, weights, imagedata, amount); data[dotIndex] = gaussianDot.r; data[dotIndex + 1] = gaussianDot.g; data[dotIndex + 2] = gaussianDot.b; data[dotIndex + 3] = gaussianDot.a; } } return imagedata } function getGaussianDot (x, y, weights, imagedata, amount) { var w = imagedata.width; var h = imagedata.height; var dotIndex = x * 4 + y * 4 * w; var tempDotIndex; var matrixObj = getDotMatrix(x, y, imagedata, amount, weights); var dotMatrix = matrixObj.list; var allWeights = matrixObj.allweights; var ret = { r: 0, g: 0, b: 0, a: 0 }; for (var i = 0; i < dotMatrix.length; i++) { tempDotIndex = dotIndex + dotMatrix[i]['x'] * 4 + dotMatrix[i]['y'] * w * 4; ret.r += imagedata.data[tempDotIndex] * dotMatrix[i]['weight'] / allWeights; ret.g += imagedata.data[tempDotIndex + 1] * dotMatrix[i]['weight'] / allWeights; ret.b += imagedata.data[tempDotIndex + 2] * dotMatrix[i]['weight'] / allWeights; ret.a += imagedata.data[tempDotIndex + 3] * dotMatrix[i]['weight'] / allWeights; } return ret } // 获取已目标点为中心的半径为amount的实际weights矩阵 function getDotMatrix (x, y, imagedata, amount, weights) { var i,j; var ret = []; var allweights = 0; for (i = -amount; i <= amount; i++) { for (j = -amount; j <= amount; j++) { // 将周围存在的点推入栈中 if ((x + i) >= 0 && (x + i) < imagedata.width && (y + j) >= 0 && (y + j) < imagedata.height) { ret.push({x: i, y: j, weight: weights[i][j]}); allweights += weights[i][j]; } } } return {list: ret, allweights: allweights} } function getWeights (amount) { var i,j; var ret = {}; for (i = -amount ; i <= amount; i++) { ret[i] = {}; for (j = -amount; j <= amount; j++) { ret[i][j] = gaussian(i, j, amount); } } return ret } function gaussian (x, y, deviation) { var ret = Math.exp( - (x * x + y * y) / (2 * deviation * deviation) ) / (2 * Math.PI * deviation * deviation); return ret } function brightness$1 (imagedata, opts) { var i = 0; var data = imagedata.data; var len = data.length; var opts = opts || {amount: 0}; var amount = +opts.amount || 0; var r,g,b; for (; i < len; i += 4) { r = data[i] * amount; g = data[i + 1] * amount; b = data[i + 2] * amount; data[i] = r; data[i + 1] = g; data[i + 2] = b; } return imagedata } // TODO function contrast$1 (imagedata, opts) { var i = 0; var data = imagedata.data; var len = data.length; var opts = opts || {amount: 0}; var amount = +opts.amount || 0; var r,g,b; for (; i < len; i += 4) { // r = data[i] * amount + intercept // g = data[i + 1] * amount + intercept // b = data[i + 2] * amount + intercept r = 128 + (data[i] - 128) * amount; g = 128 + (data[i + 1] - 128) * amount; b = 128 + (data[i + 2] - 128) * amount; data[i] = r; data[i + 1] = g; data[i + 2] = b; } return imagedata } // according to https://drafts.fxtf.org/filter-effects/#opacityEquivalent function opacity$1 (imagedata, opts) { var i = 0; var data = imagedata.data; var len = data.length; var opts = opts || {amount: 0}; var amount = +opts.amount || 0; var a; var tableValues = [0, +amount]; for (; i < len; i += 4) { a = getInterpolation(data[i + 3] / 255, tableValues); data[i + 3] = a * 255; } return imagedata } function getInterpolation (c, tableValues) { if (c === 1) { return tableValues[1] } return tableValues[0] + c * (tableValues[1] - tableValues[0]) } // according to https://drafts.fxtf.org/filter-effects/#invertEquivalent // not consistency of css3 filter invert when amount > 1 function invert$1 (imagedata, opts) { var i = 0; var data = imagedata.data; var len = data.length; var opts = opts || {amount: 0}; var amount = +opts.amount || 0; var r,g,b; var tableValues = [+amount, 1 - amount]; for (; i < len; i += 4) { r = getInterpolation$1(data[i] / 255, tableValues); g = getInterpolation$1(data[i + 1] / 255, tableValues); b = getInterpolation$1(data[i + 2] / 255, tableValues); data[i] = r * 255; data[i + 1] = g * 255; data[i + 2] = b * 255; } return imagedata } function getInterpolation$1 (c, tableValues) { if (c === 1) { return tableValues[1] } return tableValues[0] + c * (tableValues[1] - tableValues[0]) } var index = { grayscale: grayscale$1, saturate: saturate$1, sepia: sepia$1, hueRotate: hueRotate$1, blur: blur$1, brightness: brightness$1, contrast: contrast$1, opacity: opacity$1, invert: invert$1 } return index; })));