UNPKG

mighty-webcamjs

Version:

HTML5 Webcam Image Capture Library with Flash Fallback

920 lines (824 loc) 23.9 kB
// source: https://github.com/CezaryDanielNowak/inspector-bokeh/ (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.measureBlur = 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){ var Filters = require('canvasfilters').Filters; function detectEdges(imageData) { var greyscaled, sobelKernel; if (imageData.width >= 360) { greyscaled = Filters.luminance(Filters.gaussianBlur(imageData, 5.0)); } else { greyscaled = Filters.luminance(imageData); } sobelKernel = Filters.getFloat32Array( [1, 0, -1, 2, 0, -2, 1, 0, -1]); return Filters.convolve(greyscaled, sobelKernel, true); } // Reduce imageData from RGBA to only one channel (Y/luminance after conversion to greyscale) // since RGB all have the same values and Alpha was ignored. function reducedPixels(imageData) { var i, x, y, row, pixels = imageData.data, rowLen = imageData.width * 4, rows = []; for (y = 0; y < pixels.length; y += rowLen) { row = new Uint8ClampedArray(imageData.width); x = 0; for (i = y; i < y + rowLen; i += 4) { row[x] = pixels[i]; x += 1; } rows.push(row); } return rows; } // pixels = Array of Uint8ClampedArrays (row in original image) function detectBlur(pixels) { var x, y, value, oldValue, edgeStart, edgeWidth, bm, percWidth, width = pixels[0].length, height = pixels.length, numEdges = 0, sumEdgeWidths = 0, edgeIntensThresh = 20; for (y = 0; y < height; y += 1) { // Reset edge marker, none found yet edgeStart = -1; for (x = 0; x < width; x += 1) { value = pixels[y][x]; // Edge is still open if (edgeStart >= 0 && x > edgeStart) { oldValue = pixels[y][x - 1]; // Value stopped increasing => edge ended if (value < oldValue) { // Only count edges that reach a certain intensity if (oldValue >= edgeIntensThresh) { edgeWidth = x - edgeStart - 1; numEdges += 1; sumEdgeWidths += edgeWidth; } edgeStart = -1; // Reset edge marker } } // Edge starts if (value == 0) { edgeStart = x; } } } if (numEdges === 0) { bm = 0; percWidth = 0; } else { bm = sumEdgeWidths / numEdges; percWidth = bm / width * 100; } return { width: width, height: height, num_edges: numEdges, avg_edge_width: bm, avg_edge_width_perc: percWidth }; } function measureBlur(imageData) { return detectBlur(reducedPixels(detectEdges(imageData))); } measureBlur.setup = function() { throw new Error('[inspector-bokeh error] Setup is availabe only in inspector-bookeh/async!'); }; module.exports = measureBlur; },{"canvasfilters":2}],2:[function(require,module,exports){ var Filters = {}; if (typeof Float32Array == 'undefined') { Filters.getFloat32Array = Filters.getUint8Array = function(len) { if (len.length) { return len.slice(0); } return new Array(len); }; } else { Filters.getFloat32Array = function(len) { return new Float32Array(len); }; Filters.getUint8Array = function(len) { return new Uint8Array(len); }; } if (typeof document != 'undefined') { Filters.tmpCanvas = document.createElement('canvas'); Filters.tmpCtx = Filters.tmpCanvas.getContext('2d'); Filters.getPixels = function(img) { var c,ctx; if (img.getContext) { c = img; try { ctx = c.getContext('2d'); } catch(e) {} } if (!ctx) { c = this.getCanvas(img.width, img.height); ctx = c.getContext('2d'); ctx.drawImage(img, 0, 0); } return ctx.getImageData(0,0,c.width,c.height); }; Filters.createImageData = function(w, h) { return this.tmpCtx.createImageData(w, h); }; Filters.getCanvas = function(w,h) { var c = document.createElement('canvas'); c.width = w; c.height = h; return c; }; Filters.filterImage = function(filter, image, var_args) { var args = [this.getPixels(image)]; for (var i=2; i<arguments.length; i++) { args.push(arguments[i]); } return filter.apply(this, args); }; Filters.toCanvas = function(pixels) { var canvas = this.getCanvas(pixels.width, pixels.height); canvas.getContext('2d').putImageData(pixels, 0, 0); return canvas; }; Filters.toImageData = function(pixels) { return this.identity(pixels); }; } else { onmessage = function(e) { var ds = e.data; if (!ds.length) { ds = [ds]; } postMessage(Filters.runPipeline(ds)); }; Filters.createImageData = function(w, h) { return {width: w, height: h, data: this.getFloat32Array(w*h*4)}; }; } Filters.runPipeline = function(ds) { var res = null; res = this[ds[0].name].apply(this, ds[0].args); for (var i=1; i<ds.length; i++) { var d = ds[i]; var args = d.args.slice(0); args.unshift(res); res = this[d.name].apply(this, args); } return res; }; Filters.createImageDataFloat32 = function(w, h) { return {width: w, height: h, data: this.getFloat32Array(w*h*4)}; }; Filters.identity = function(pixels, args) { var output = Filters.createImageData(pixels.width, pixels.height); var dst = output.data; var d = pixels.data; for (var i=0; i<d.length; i++) { dst[i] = d[i]; } return output; }; Filters.horizontalFlip = function(pixels) { var output = Filters.createImageData(pixels.width, pixels.height); var w = pixels.width; var h = pixels.height; var dst = output.data; var d = pixels.data; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var off = (y*w+x)*4; var dstOff = (y*w+(w-x-1))*4; dst[dstOff] = d[off]; dst[dstOff+1] = d[off+1]; dst[dstOff+2] = d[off+2]; dst[dstOff+3] = d[off+3]; } } return output; }; Filters.verticalFlip = function(pixels) { var output = Filters.createImageData(pixels.width, pixels.height); var w = pixels.width; var h = pixels.height; var dst = output.data; var d = pixels.data; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var off = (y*w+x)*4; var dstOff = ((h-y-1)*w+x)*4; dst[dstOff] = d[off]; dst[dstOff+1] = d[off+1]; dst[dstOff+2] = d[off+2]; dst[dstOff+3] = d[off+3]; } } return output; }; Filters.luminance = function(pixels, args) { var output = Filters.createImageData(pixels.width, pixels.height); var dst = output.data; var d = pixels.data; for (var i=0; i<d.length; i+=4) { var r = d[i]; var g = d[i+1]; var b = d[i+2]; // CIE luminance for the RGB var v = 0.2126*r + 0.7152*g + 0.0722*b; dst[i] = dst[i+1] = dst[i+2] = v; dst[i+3] = d[i+3]; } return output; }; Filters.grayscale = function(pixels, args) { var output = Filters.createImageData(pixels.width, pixels.height); var dst = output.data; var d = pixels.data; for (var i=0; i<d.length; i+=4) { var r = d[i]; var g = d[i+1]; var b = d[i+2]; var v = 0.3*r + 0.59*g + 0.11*b; dst[i] = dst[i+1] = dst[i+2] = v; dst[i+3] = d[i+3]; } return output; }; Filters.grayscaleAvg = function(pixels, args) { var output = Filters.createImageData(pixels.width, pixels.height); var dst = output.data; var d = pixels.data; var f = 1/3; for (var i=0; i<d.length; i+=4) { var r = d[i]; var g = d[i+1]; var b = d[i+2]; var v = (r+g+b) * f; dst[i] = dst[i+1] = dst[i+2] = v; dst[i+3] = d[i+3]; } return output; }; Filters.threshold = function(pixels, threshold, high, low) { var output = Filters.createImageData(pixels.width, pixels.height); if (high == null) high = 255; if (low == null) low = 0; var d = pixels.data; var dst = output.data; for (var i=0; i<d.length; i+=4) { var r = d[i]; var g = d[i+1]; var b = d[i+2]; var v = (0.3*r + 0.59*g + 0.11*b >= threshold) ? high : low; dst[i] = dst[i+1] = dst[i+2] = v; dst[i+3] = d[i+3]; } return output; }; Filters.invert = function(pixels) { var output = Filters.createImageData(pixels.width, pixels.height); var d = pixels.data; var dst = output.data; for (var i=0; i<d.length; i+=4) { dst[i] = 255-d[i]; dst[i+1] = 255-d[i+1]; dst[i+2] = 255-d[i+2]; dst[i+3] = d[i+3]; } return output; }; Filters.brightnessContrast = function(pixels, brightness, contrast) { var lut = this.brightnessContrastLUT(brightness, contrast); return this.applyLUT(pixels, {r:lut, g:lut, b:lut, a:this.identityLUT()}); }; Filters.applyLUT = function(pixels, lut) { var output = Filters.createImageData(pixels.width, pixels.height); var d = pixels.data; var dst = output.data; var r = lut.r; var g = lut.g; var b = lut.b; var a = lut.a; for (var i=0; i<d.length; i+=4) { dst[i] = r[d[i]]; dst[i+1] = g[d[i+1]]; dst[i+2] = b[d[i+2]]; dst[i+3] = a[d[i+3]]; } return output; }; Filters.createLUTFromCurve = function(points) { var lut = this.getUint8Array(256); var p = [0, 0]; for (var i=0,j=0; i<lut.length; i++) { while (j < points.length && points[j][0] < i) { p = points[j]; j++; } lut[i] = p[1]; } return lut; }; Filters.identityLUT = function() { var lut = this.getUint8Array(256); for (var i=0; i<lut.length; i++) { lut[i] = i; } return lut; }; Filters.invertLUT = function() { var lut = this.getUint8Array(256); for (var i=0; i<lut.length; i++) { lut[i] = 255-i; } return lut; }; Filters.brightnessContrastLUT = function(brightness, contrast) { var lut = this.getUint8Array(256); var contrastAdjust = -128*contrast + 128; var brightnessAdjust = 255 * brightness; var adjust = contrastAdjust + brightnessAdjust; for (var i=0; i<lut.length; i++) { var c = i*contrast + adjust; lut[i] = c < 0 ? 0 : (c > 255 ? 255 : c); } return lut; }; Filters.convolve = function(pixels, weights, opaque) { var side = Math.round(Math.sqrt(weights.length)); var halfSide = Math.floor(side/2); var src = pixels.data; var sw = pixels.width; var sh = pixels.height; var w = sw; var h = sh; var output = Filters.createImageData(w, h); var dst = output.data; var alphaFac = opaque ? 1 : 0; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var sy = y; var sx = x; var dstOff = (y*w+x)*4; var r=0, g=0, b=0, a=0; for (var cy=0; cy<side; cy++) { for (var cx=0; cx<side; cx++) { var scy = Math.min(sh-1, Math.max(0, sy + cy - halfSide)); var scx = Math.min(sw-1, Math.max(0, sx + cx - halfSide)); var srcOff = (scy*sw+scx)*4; var wt = weights[cy*side+cx]; r += src[srcOff] * wt; g += src[srcOff+1] * wt; b += src[srcOff+2] * wt; a += src[srcOff+3] * wt; } } dst[dstOff] = r; dst[dstOff+1] = g; dst[dstOff+2] = b; dst[dstOff+3] = a + alphaFac*(255-a); } } return output; }; Filters.verticalConvolve = function(pixels, weightsVector, opaque) { var side = weightsVector.length; var halfSide = Math.floor(side/2); var src = pixels.data; var sw = pixels.width; var sh = pixels.height; var w = sw; var h = sh; var output = Filters.createImageData(w, h); var dst = output.data; var alphaFac = opaque ? 1 : 0; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var sy = y; var sx = x; var dstOff = (y*w+x)*4; var r=0, g=0, b=0, a=0; for (var cy=0; cy<side; cy++) { var scy = Math.min(sh-1, Math.max(0, sy + cy - halfSide)); var scx = sx; var srcOff = (scy*sw+scx)*4; var wt = weightsVector[cy]; r += src[srcOff] * wt; g += src[srcOff+1] * wt; b += src[srcOff+2] * wt; a += src[srcOff+3] * wt; } dst[dstOff] = r; dst[dstOff+1] = g; dst[dstOff+2] = b; dst[dstOff+3] = a + alphaFac*(255-a); } } return output; }; Filters.horizontalConvolve = function(pixels, weightsVector, opaque) { var side = weightsVector.length; var halfSide = Math.floor(side/2); var src = pixels.data; var sw = pixels.width; var sh = pixels.height; var w = sw; var h = sh; var output = Filters.createImageData(w, h); var dst = output.data; var alphaFac = opaque ? 1 : 0; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var sy = y; var sx = x; var dstOff = (y*w+x)*4; var r=0, g=0, b=0, a=0; for (var cx=0; cx<side; cx++) { var scy = sy; var scx = Math.min(sw-1, Math.max(0, sx + cx - halfSide)); var srcOff = (scy*sw+scx)*4; var wt = weightsVector[cx]; r += src[srcOff] * wt; g += src[srcOff+1] * wt; b += src[srcOff+2] * wt; a += src[srcOff+3] * wt; } dst[dstOff] = r; dst[dstOff+1] = g; dst[dstOff+2] = b; dst[dstOff+3] = a + alphaFac*(255-a); } } return output; }; Filters.separableConvolve = function(pixels, horizWeights, vertWeights, opaque) { return this.horizontalConvolve( this.verticalConvolveFloat32(pixels, vertWeights, opaque), horizWeights, opaque ); }; Filters.convolveFloat32 = function(pixels, weights, opaque) { var side = Math.round(Math.sqrt(weights.length)); var halfSide = Math.floor(side/2); var src = pixels.data; var sw = pixels.width; var sh = pixels.height; var w = sw; var h = sh; var output = Filters.createImageDataFloat32(w, h); var dst = output.data; var alphaFac = opaque ? 1 : 0; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var sy = y; var sx = x; var dstOff = (y*w+x)*4; var r=0, g=0, b=0, a=0; for (var cy=0; cy<side; cy++) { for (var cx=0; cx<side; cx++) { var scy = Math.min(sh-1, Math.max(0, sy + cy - halfSide)); var scx = Math.min(sw-1, Math.max(0, sx + cx - halfSide)); var srcOff = (scy*sw+scx)*4; var wt = weights[cy*side+cx]; r += src[srcOff] * wt; g += src[srcOff+1] * wt; b += src[srcOff+2] * wt; a += src[srcOff+3] * wt; } } dst[dstOff] = r; dst[dstOff+1] = g; dst[dstOff+2] = b; dst[dstOff+3] = a + alphaFac*(255-a); } } return output; }; Filters.verticalConvolveFloat32 = function(pixels, weightsVector, opaque) { var side = weightsVector.length; var halfSide = Math.floor(side/2); var src = pixels.data; var sw = pixels.width; var sh = pixels.height; var w = sw; var h = sh; var output = Filters.createImageDataFloat32(w, h); var dst = output.data; var alphaFac = opaque ? 1 : 0; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var sy = y; var sx = x; var dstOff = (y*w+x)*4; var r=0, g=0, b=0, a=0; for (var cy=0; cy<side; cy++) { var scy = Math.min(sh-1, Math.max(0, sy + cy - halfSide)); var scx = sx; var srcOff = (scy*sw+scx)*4; var wt = weightsVector[cy]; r += src[srcOff] * wt; g += src[srcOff+1] * wt; b += src[srcOff+2] * wt; a += src[srcOff+3] * wt; } dst[dstOff] = r; dst[dstOff+1] = g; dst[dstOff+2] = b; dst[dstOff+3] = a + alphaFac*(255-a); } } return output; }; Filters.horizontalConvolveFloat32 = function(pixels, weightsVector, opaque) { var side = weightsVector.length; var halfSide = Math.floor(side/2); var src = pixels.data; var sw = pixels.width; var sh = pixels.height; var w = sw; var h = sh; var output = Filters.createImageDataFloat32(w, h); var dst = output.data; var alphaFac = opaque ? 1 : 0; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var sy = y; var sx = x; var dstOff = (y*w+x)*4; var r=0, g=0, b=0, a=0; for (var cx=0; cx<side; cx++) { var scy = sy; var scx = Math.min(sw-1, Math.max(0, sx + cx - halfSide)); var srcOff = (scy*sw+scx)*4; var wt = weightsVector[cx]; r += src[srcOff] * wt; g += src[srcOff+1] * wt; b += src[srcOff+2] * wt; a += src[srcOff+3] * wt; } dst[dstOff] = r; dst[dstOff+1] = g; dst[dstOff+2] = b; dst[dstOff+3] = a + alphaFac*(255-a); } } return output; }; Filters.separableConvolveFloat32 = function(pixels, horizWeights, vertWeights, opaque) { return this.horizontalConvolveFloat32( this.verticalConvolveFloat32(pixels, vertWeights, opaque), horizWeights, opaque ); }; Filters.gaussianBlur = function(pixels, diameter) { diameter = Math.abs(diameter); if (diameter <= 1) return Filters.identity(pixels); var radius = diameter / 2; var len = Math.ceil(diameter) + (1 - (Math.ceil(diameter) % 2)) var weights = this.getFloat32Array(len); var rho = (radius+0.5) / 3; var rhoSq = rho*rho; var gaussianFactor = 1 / Math.sqrt(2*Math.PI*rhoSq); var rhoFactor = -1 / (2*rho*rho) var wsum = 0; var middle = Math.floor(len/2); for (var i=0; i<len; i++) { var x = i-middle; var gx = gaussianFactor * Math.exp(x*x*rhoFactor); weights[i] = gx; wsum += gx; } for (var i=0; i<weights.length; i++) { weights[i] /= wsum; } return Filters.separableConvolve(pixels, weights, weights, false); }; Filters.laplaceKernel = Filters.getFloat32Array( [-1,-1,-1, -1, 8,-1, -1,-1,-1]); Filters.laplace = function(pixels) { return Filters.convolve(pixels, this.laplaceKernel, true); }; Filters.sobelSignVector = Filters.getFloat32Array([-1,0,1]); Filters.sobelScaleVector = Filters.getFloat32Array([1,2,1]); Filters.sobelVerticalGradient = function(px) { return this.separableConvolveFloat32(px, this.sobelSignVector, this.sobelScaleVector); }; Filters.sobelHorizontalGradient = function(px) { return this.separableConvolveFloat32(px, this.sobelScaleVector, this.sobelSignVector); }; Filters.sobelVectors = function(px) { var vertical = this.sobelVerticalGradient(px); var horizontal = this.sobelHorizontalGradient(px); var id = {width: vertical.width, height: vertical.height, data: this.getFloat32Array(vertical.width*vertical.height*8)}; var vd = vertical.data; var hd = horizontal.data; var idd = id.data; for (var i=0,j=0; i<idd.length; i+=2,j++) { idd[i] = hd[j]; idd[i+1] = vd[j]; } return id; }; Filters.sobel = function(px) { px = this.grayscale(px); var vertical = this.sobelVerticalGradient(px); var horizontal = this.sobelHorizontalGradient(px); var id = this.createImageData(vertical.width, vertical.height); for (var i=0; i<id.data.length; i+=4) { var v = Math.abs(vertical.data[i]); id.data[i] = v; var h = Math.abs(horizontal.data[i]); id.data[i+1] = h; id.data[i+2] = (v+h)/4; id.data[i+3] = 255; } return id; }; Filters.bilinearSample = function (pixels, x, y, rgba) { var x1 = Math.floor(x); var x2 = Math.ceil(x); var y1 = Math.floor(y); var y2 = Math.ceil(y); var a = (x1+pixels.width*y1)*4; var b = (x2+pixels.width*y1)*4; var c = (x1+pixels.width*y2)*4; var d = (x2+pixels.width*y2)*4; var df = ((x-x1) + (y-y1)); var cf = ((x2-x) + (y-y1)); var bf = ((x-x1) + (y2-y)); var af = ((x2-x) + (y2-y)); var rsum = 1/(af+bf+cf+df); af *= rsum; bf *= rsum; cf *= rsum; df *= rsum; var data = pixels.data; rgba[0] = data[a]*af + data[b]*bf + data[c]*cf + data[d]*df; rgba[1] = data[a+1]*af + data[b+1]*bf + data[c+1]*cf + data[d+1]*df; rgba[2] = data[a+2]*af + data[b+2]*bf + data[c+2]*cf + data[d+2]*df; rgba[3] = data[a+3]*af + data[b+3]*bf + data[c+3]*cf + data[d+3]*df; return rgba; }; Filters.distortSine = function(pixels, amount, yamount) { if (amount == null) amount = 0.5; if (yamount == null) yamount = amount; var output = this.createImageData(pixels.width, pixels.height); var dst = output.data; var d = pixels.data; var px = this.createImageData(1,1).data; for (var y=0; y<output.height; y++) { var sy = -Math.sin(y/(output.height-1) * Math.PI*2); var srcY = y + sy * yamount * output.height/4; srcY = Math.max(Math.min(srcY, output.height-1), 0); for (var x=0; x<output.width; x++) { var sx = -Math.sin(x/(output.width-1) * Math.PI*2); var srcX = x + sx * amount * output.width/4; srcX = Math.max(Math.min(srcX, output.width-1), 0); var rgba = this.bilinearSample(pixels, srcX, srcY, px); var off = (y*output.width+x)*4; dst[off] = rgba[0]; dst[off+1] = rgba[1]; dst[off+2] = rgba[2]; dst[off+3] = rgba[3]; } } return output; }; Filters.darkenBlend = function(below, above) { var output = Filters.createImageData(below.width, below.height); var a = below.data; var b = above.data; var dst = output.data; var f = 1/255; for (var i=0; i<a.length; i+=4) { dst[i] = a[i] < b[i] ? a[i] : b[i]; dst[i+1] = a[i+1] < b[i+1] ? a[i+1] : b[i+1]; dst[i+2] = a[i+2] < b[i+2] ? a[i+2] : b[i+2]; dst[i+3] = a[i+3]+((255-a[i+3])*b[i+3])*f; } return output; }; Filters.lightenBlend = function(below, above) { var output = Filters.createImageData(below.width, below.height); var a = below.data; var b = above.data; var dst = output.data; var f = 1/255; for (var i=0; i<a.length; i+=4) { dst[i] = a[i] > b[i] ? a[i] : b[i]; dst[i+1] = a[i+1] > b[i+1] ? a[i+1] : b[i+1]; dst[i+2] = a[i+2] > b[i+2] ? a[i+2] : b[i+2]; dst[i+3] = a[i+3]+((255-a[i+3])*b[i+3])*f; } return output; }; Filters.multiplyBlend = function(below, above) { var output = Filters.createImageData(below.width, below.height); var a = below.data; var b = above.data; var dst = output.data; var f = 1/255; for (var i=0; i<a.length; i+=4) { dst[i] = (a[i]*b[i])*f; dst[i+1] = (a[i+1]*b[i+1])*f; dst[i+2] = (a[i+2]*b[i+2])*f; dst[i+3] = a[i+3]+((255-a[i+3])*b[i+3])*f; } return output; }; Filters.screenBlend = function(below, above) { var output = Filters.createImageData(below.width, below.height); var a = below.data; var b = above.data; var dst = output.data; var f = 1/255; for (var i=0; i<a.length; i+=4) { dst[i] = a[i]+b[i]-a[i]*b[i]*f; dst[i+1] = a[i+1]+b[i+1]-a[i+1]*b[i+1]*f; dst[i+2] = a[i+2]+b[i+2]-a[i+2]*b[i+2]*f; dst[i+3] = a[i+3]+((255-a[i+3])*b[i+3])*f; } return output; }; Filters.addBlend = function(below, above) { var output = Filters.createImageData(below.width, below.height); var a = below.data; var b = above.data; var dst = output.data; var f = 1/255; for (var i=0; i<a.length; i+=4) { dst[i] = (a[i]+b[i]); dst[i+1] = (a[i+1]+b[i+1]); dst[i+2] = (a[i+2]+b[i+2]); dst[i+3] = a[i+3]+((255-a[i+3])*b[i+3])*f; } return output; }; Filters.subBlend = function(below, above) { var output = Filters.createImageData(below.width, below.height); var a = below.data; var b = above.data; var dst = output.data; var f = 1/255; for (var i=0; i<a.length; i+=4) { dst[i] = (a[i]+b[i]-255); dst[i+1] = (a[i+1]+b[i+1]-255); dst[i+2] = (a[i+2]+b[i+2]-255); dst[i+3] = a[i+3]+((255-a[i+3])*b[i+3])*f; } return output; }; Filters.differenceBlend = function(below, above) { var output = Filters.createImageData(below.width, below.height); var a = below.data; var b = above.data; var dst = output.data; var f = 1/255; for (var i=0; i<a.length; i+=4) { dst[i] = Math.abs(a[i]-b[i]); dst[i+1] = Math.abs(a[i+1]-b[i+1]); dst[i+2] = Math.abs(a[i+2]-b[i+2]); dst[i+3] = a[i+3]+((255-a[i+3])*b[i+3])*f; } return output; }; Filters.erode = function(pixels) { var src = pixels.data; var sw = pixels.width; var sh = pixels.height; var w = sw; var h = sh; var output = Filters.createImageData(w, h); var dst = output.data; for (var y=0; y<h; y++) { for (var x=0; x<w; x++) { var sy = y; var sx = x; var dstOff = (y*w+x)*4; var srcOff = (sy*sw+sx)*4; var v = 0; if (src[srcOff] == 0) { if (src[(sy*sw+Math.max(0,sx-1))*4] == 0 && src[(Math.max(0,sy-1)*sw+sx)*4] == 0) { v = 255; } } else { v = 255; } dst[dstOff] = v; dst[dstOff+1] = v; dst[dstOff+2] = v; dst[dstOff+3] = 255; } } return output; }; if (typeof require != 'undefined') { exports.Filters = Filters; } },{}]},{},[1])(1) });