scrawl-canvas
Version:
Version 8.9.4 - 19 Nov 2022
769 lines (516 loc) • 240 kB
HTML
<!DOCTYPE html>
<html>
<head>
<title>Filter factory</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="../../docco.css" />
</head>
<body>
<div id="container">
<div id="background"></div>
<ul id="jump_to">
<li>
<a class="large" href="javascript:void(0);">Jump To …</a>
<a class="small" href="javascript:void(0);">+</a>
<div id="jump_wrapper">
<div id="jump_page_wrapper">
<div id="jump_page">
<a class="source" href="../core/animationloop.html">
./source/core/animationloop.js
</a>
<a class="source" href="../core/document.html">
./source/core/document.js
</a>
<a class="source" href="../core/events.html">
./source/core/events.js
</a>
<a class="source" href="../core/init.html">
./source/core/init.js
</a>
<a class="source" href="../core/library.html">
./source/core/library.js
</a>
<a class="source" href="../core/random-seed.html">
./source/core/random-seed.js
</a>
<a class="source" href="../core/snippets.html">
./source/core/snippets.js
</a>
<a class="source" href="../core/userInteraction.html">
./source/core/userInteraction.js
</a>
<a class="source" href="../core/utilities.html">
./source/core/utilities.js
</a>
<a class="source" href="action.html">
./source/factory/action.js
</a>
<a class="source" href="anchor.html">
./source/factory/anchor.js
</a>
<a class="source" href="animation.html">
./source/factory/animation.js
</a>
<a class="source" href="bezier.html">
./source/factory/bezier.js
</a>
<a class="source" href="block.html">
./source/factory/block.js
</a>
<a class="source" href="canvas.html">
./source/factory/canvas.js
</a>
<a class="source" href="cell.html">
./source/factory/cell.js
</a>
<a class="source" href="cog.html">
./source/factory/cog.js
</a>
<a class="source" href="color.html">
./source/factory/color.js
</a>
<a class="source" href="conicGradient.html">
./source/factory/conicGradient.js
</a>
<a class="source" href="coordinate.html">
./source/factory/coordinate.js
</a>
<a class="source" href="crescent.html">
./source/factory/crescent.js
</a>
<a class="source" href="element.html">
./source/factory/element.js
</a>
<a class="source" href="emitter.html">
./source/factory/emitter.js
</a>
<a class="source" href="filter.html">
./source/factory/filter.js
</a>
<a class="source" href="filterEngine-bluenoiseData.html">
./source/factory/filterEngine-bluenoiseData.js
</a>
<a class="source" href="filterEngine.html">
./source/factory/filterEngine.js
</a>
<a class="source" href="fontAttributes.html">
./source/factory/fontAttributes.js
</a>
<a class="source" href="gradient.html">
./source/factory/gradient.js
</a>
<a class="source" href="grid.html">
./source/factory/grid.js
</a>
<a class="source" href="group.html">
./source/factory/group.js
</a>
<a class="source" href="imageAsset.html">
./source/factory/imageAsset.js
</a>
<a class="source" href="line.html">
./source/factory/line.js
</a>
<a class="source" href="lineSpiral.html">
./source/factory/lineSpiral.js
</a>
<a class="source" href="loom.html">
./source/factory/loom.js
</a>
<a class="source" href="mesh.html">
./source/factory/mesh.js
</a>
<a class="source" href="net.html">
./source/factory/net.js
</a>
<a class="source" href="noiseAsset.html">
./source/factory/noiseAsset.js
</a>
<a class="source" href="oval.html">
./source/factory/oval.js
</a>
<a class="source" href="palette.html">
./source/factory/palette.js
</a>
<a class="source" href="particle.html">
./source/factory/particle.js
</a>
<a class="source" href="particleForce.html">
./source/factory/particleForce.js
</a>
<a class="source" href="particleHistory.html">
./source/factory/particleHistory.js
</a>
<a class="source" href="particleSpring.html">
./source/factory/particleSpring.js
</a>
<a class="source" href="particleWorld.html">
./source/factory/particleWorld.js
</a>
<a class="source" href="pattern.html">
./source/factory/pattern.js
</a>
<a class="source" href="phrase.html">
./source/factory/phrase.js
</a>
<a class="source" href="picture.html">
./source/factory/picture.js
</a>
<a class="source" href="polygon.html">
./source/factory/polygon.js
</a>
<a class="source" href="polyline.html">
./source/factory/polyline.js
</a>
<a class="source" href="quadratic.html">
./source/factory/quadratic.js
</a>
<a class="source" href="quaternion.html">
./source/factory/quaternion.js
</a>
<a class="source" href="radialGradient.html">
./source/factory/radialGradient.js
</a>
<a class="source" href="rawAsset.html">
./source/factory/rawAsset.js
</a>
<a class="source" href="rdAsset.html">
./source/factory/rdAsset.js
</a>
<a class="source" href="rectangle.html">
./source/factory/rectangle.js
</a>
<a class="source" href="renderAnimation.html">
./source/factory/renderAnimation.js
</a>
<a class="source" href="shape.html">
./source/factory/shape.js
</a>
<a class="source" href="spiral.html">
./source/factory/spiral.js
</a>
<a class="source" href="spriteAsset.html">
./source/factory/spriteAsset.js
</a>
<a class="source" href="stack.html">
./source/factory/stack.js
</a>
<a class="source" href="star.html">
./source/factory/star.js
</a>
<a class="source" href="state.html">
./source/factory/state.js
</a>
<a class="source" href="tetragon.html">
./source/factory/tetragon.js
</a>
<a class="source" href="ticker.html">
./source/factory/ticker.js
</a>
<a class="source" href="tracer.html">
./source/factory/tracer.js
</a>
<a class="source" href="tween.html">
./source/factory/tween.js
</a>
<a class="source" href="unstackedElement.html">
./source/factory/unstackedElement.js
</a>
<a class="source" href="vector.html">
./source/factory/vector.js
</a>
<a class="source" href="videoAsset.html">
./source/factory/videoAsset.js
</a>
<a class="source" href="wheel.html">
./source/factory/wheel.js
</a>
<a class="source" href="../mixin/anchor.html">
./source/mixin/anchor.js
</a>
<a class="source" href="../mixin/asset.html">
./source/mixin/asset.js
</a>
<a class="source" href="../mixin/assetAdvancedFunctionality.html">
./source/mixin/assetAdvancedFunctionality.js
</a>
<a class="source" href="../mixin/assetConsumer.html">
./source/mixin/assetConsumer.js
</a>
<a class="source" href="../mixin/base.html">
./source/mixin/base.js
</a>
<a class="source" href="../mixin/cascade.html">
./source/mixin/cascade.js
</a>
<a class="source" href="../mixin/delta.html">
./source/mixin/delta.js
</a>
<a class="source" href="../mixin/displayShape.html">
./source/mixin/displayShape.js
</a>
<a class="source" href="../mixin/dom.html">
./source/mixin/dom.js
</a>
<a class="source" href="../mixin/entity.html">
./source/mixin/entity.js
</a>
<a class="source" href="../mixin/filter.html">
./source/mixin/filter.js
</a>
<a class="source" href="../mixin/mimic.html">
./source/mixin/mimic.js
</a>
<a class="source" href="../mixin/path.html">
./source/mixin/path.js
</a>
<a class="source" href="../mixin/pattern.html">
./source/mixin/pattern.js
</a>
<a class="source" href="../mixin/pivot.html">
./source/mixin/pivot.js
</a>
<a class="source" href="../mixin/position.html">
./source/mixin/position.js
</a>
<a class="source" href="../mixin/shapeBasic.html">
./source/mixin/shapeBasic.js
</a>
<a class="source" href="../mixin/shapeCurve.html">
./source/mixin/shapeCurve.js
</a>
<a class="source" href="../mixin/shapePathCalculation.html">
./source/mixin/shapePathCalculation.js
</a>
<a class="source" href="../mixin/styles.html">
./source/mixin/styles.js
</a>
<a class="source" href="../mixin/tween.html">
./source/mixin/tween.js
</a>
</div>
</div>
</li>
</ul>
<ul class="sections">
<li id="section-1">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-1">§</a>
</div>
<h1 id="filter-factory">Filter factory</h1>
<p>Filters take in an image representation of an <a href="../mixin/entity.html">entity</a>, <a href="./group.html">Group</a> of entitys or a <a href="./cell.html">Cell</a> display and, by manipulating the image’s data, return an updated image which replaces those entitys or Cell in the final output display.</p>
<p>Scrawl-canvas defines its filters in <strong>Filter objects</strong>, detailed in this module. The functionality to make use of these objects is coded up in the <a href="../mixin/filter.html">filter mixin</a>, which is used by the Cell, Group and all entity factories.</p>
<p>The Scrawl-canvas filter engine implements a number of common filter algorithms. These algorithms - <strong>called filter actions</strong> - can be combined in a wide variety of ways, including the use of multiple pathways, to create complex filter results.</p>
<h4 id="filter-engine-actions">Filter engine actions</h4>
<p><code>alpha-to-channels</code> - Copies the alpha channel value over to the selected value or, alternatively, sets that channels value to zero, or leaves the channel’s value unchanged. Setting the appropriate “includeChannel” flags will copy the alpha channel value to that channel; when that flag is false, setting the appropriate “excludeChannel” flag will set that channel’s value to zero. Object attributes: <code>action, lineIn, lineOut, opacity, includeRed, includeGreen, includeBlue, excludeRed, excludeGreen, excludeBlue</code>.</p>
<p><code>area-alpha</code> - Places a tile schema across the input, quarters each tile and then sets the alpha channels of the pixels in selected quarters of each tile to values set in the <code>areaAlphaLevels</code> array. Can be used to create horizontal or vertical bars, or chequerboard effects. Object attributes: <code>action, lineIn, lineOut, opacity, tileWidth, tileHeight, offsetX, offsetY, gutterWidth, gutterHeight, areaAlphaLevels</code>.</p>
<p><code>average-channels</code> - Calculates an average value from each pixel’s included channels and applies that value to all channels that have not been specifically excluded; excluded channels have their values set to 0. Object attributes: <code>action, lineIn, lineOut, opacity, includeRed, includeGreen, includeBlue, excludeRed, excludeGreen, excludeBlue</code>.</p>
<p><code>binary</code> - DEPRECATED - functionality moved over to <code>threshold</code>.</p>
<p><code>blend</code> - Using two source images (from the “lineIn” and “lineMix” arguments), combine their color information using various separable and non-separable blend modes (as defined by the W3C Compositing and Blending Level 1 recommendations). The blending method is determined by the String value supplied in the <code>blend</code> argument; permitted values are: ‘color-burn’, ‘color-dodge’, ‘darken’, ‘difference’, ‘exclusion’, ‘hard-light’, ‘lighten’, ‘lighter’, ‘multiply’, ‘overlay’, ‘screen’, ‘soft-light’, ‘color’, ‘hue’, ‘luminosity’, and ‘saturation’. Note that the source images may be of different sizes: the output (lineOut) image size will be the same as the source (NOT lineIn) image; the lineMix image can be moved relative to the lineIn image using the “offsetX” and “offsetY” arguments. Object attributes: <code>action, lineIn, lineOut, lineMix, opacity, blend, offsetX, offsetY</code>.</p>
<p><code>blur</code> - Performs a multi-loop, two-step ‘horizontal-then-vertical averaging sweep’ calculation across all pixels to create a blur effect. Note that this filter is expensive, thus much slower to complete compared to other filter effects. Object attributes: <code>action, lineIn, lineOut, opacity, radius, passes, processVertical, processHorizontal, includeRed, includeGreen, includeBlue, includeAlpha, step</code>.</p>
<p><code>channels-to-alpha</code> - Calculates an average value from each pixel’s included channels and applies that value to the alpha channel. Object attributes: <code>action, lineIn, lineOut, opacity, includeRed, includeGreen, includeBlue</code>.</p>
<p><code>chroma</code> - A chroma-key effect. Using an array of ‘range’ color arrays, determine whether a pixel’s values lie entirely within a range’s values and, if true, sets that pixel’s alpha channel value to zero. Each ‘range’ color array comprises six Numbers representing [minimum-red, minimum-green, minimum-blue, maximum-red, maximum-green, maximum-blue] values. Object attributes: <code>action, lineIn, lineOut, opacity, ranges</code>.</p>
<p><code>clamp-channels</code> - Clamp each color channel to a range set by lowColor and highColor values. Object attributes: <code>action, lineIn, lineOut, opacity, lowRed, lowGreen, lowBlue, highRed, highGreen, highBlue</code>.</p>
<p><code>colors-to-alpha</code> - A chroma-key effect. Determine the alpha channel value for each pixel depending on the closeness to that pixel’s color channel values to a reference color supplied in the “red”, “green” and “blue” arguments. The sensitivity of the effect can be manipulated using the “transparentAt” and “opaqueAt” values, both of which lie in the range 0-1. Object attributes: <code>action, lineIn, lineOut, opacity, red, green, blue, opaqueAt, transparentAt</code>; pseudo-arguments for the convenience method include <code>reference</code> - any valid CSS color string from which the channel values will be calculated.</p>
<p><code>compose</code> - Using two source images (from the “lineIn” and “lineMix” arguments), combine their color information using alpha compositing rules (as defined by Porter/Duff). The compositing method is determined by the String value supplied in the “compose” argument; permitted values are: ‘destination-only’, ‘destination-over’, ‘destination-in’, ‘destination-out’, ‘destination-atop’, ‘source-only’, ‘source-over’ (default), ‘source-in’, ‘source-out’, ‘source-atop’, ‘clear’, ‘xor’, or ‘lighter’. Note that the source images may be of different sizes: the output (lineOut) image size will be the same as the source (NOT lineIn) image; the lineMix image can be moved relative to the lineIn image using the “offsetX” and “offsetY” arguments. Object attributes: <code>action, lineIn, lineOut, lineMix, opacity, compose, offsetX, offsetY</code>.</p>
<p><code>corrode</code> - Performs a special form of matrix operation on each pixel’s color and alpha channels, calculating the new value using neighbouring pixel values. Note that this filter is expensive, thus much slower to complete compared to other filter effects. The matrix dimensions can be set using the “width” and “height” arguments, while setting the home pixel’s position within the matrix can be set using the “offsetX” and “offsetY” arguments. The operation will set the pixel’s channel value to match either the ‘lowest’, ‘highest’ or ‘average’ (default) values as dictated by its neighbours - this value is set in the “level” attribute. Channels can be selected by setting the “includeRed”, “includeGreen”, “includeBlue” (all false by default) and “includeAlpha” (default: true) flags. Object attributes: <code>action, lineIn, lineOut, opacity, includeRed, includeGreen, includeBlue, includeAlpha, width, height, offsetX, offsetY, operation</code>.</p>
<p><code>displace</code> - Shift pixels around the image, based on the values supplied in a displacement process-image. Common source images can be generated from the various Noise assets, though any image will create an effect. Object attributes: <code>action, lineIn, lineOut, lineMix, opacity, channelX, channelY, scaleX, scaleY, transparentEdges, offsetX, offsetY</code>.</p>
<p><code>emboss</code> - A 3x3 matrix transform; the matrix weights are calculated internally from the values of two arguments: “strength”, and “angle” - which is a value measured in degrees, with 0 degrees pointing to the right of the origin (along the positive x axis). Post-processing options include removing unchanged pixels, or setting then to mid-gray. The convenience method includes additional arguments which will add a choice of grayscale, then channel clamping, then blurring actions before passing the results to this emboss action. Object attributes: <code>action, lineIn, lineOut, opacity, strength, angle, tolerance, keepOnlyChangedAreas, postProcessResults</code>; pseudo-arguments for the convenience method include <code>useNaturalGrayscale, clamp, smoothing</code>.</p>
<p><code>flood</code> - Set all pixels to the channel values supplied in the “red”, “green”, “blue” and “alpha” arguments. Object attributes: <code>action, lineIn, lineOut, opacity, red, green, blue, alpha</code>; pseudo-arguments for the convenience method include <code>reference</code> - any valid CSS color string from which the channel values will be calculated.</p>
<p><code>gaussianblur</code> - a fast linear gaussian blur algorithm taken from this GitHub repository: <a href="https://github.com/nodeca/glur/blob/master/index.js">https://github.com/nodeca/glur/blob/master/index.js</a> (code accessed 1 June 2021). Object attributes: <code>action, lineIn, lineOut, opacity, radius</code>.</p>
<p><code>glitch</code> - CRT television/monitor glitching effect - shifts rows horizontally by a random amount (mediated by limits). Object attributes: <code>action, lineIn, lineOut, opacity, useMixedChannel, seed, step, offsetMin, offsetMax, offsetRedMin, offsetRedMax, offsetGreenMin, offsetGreenMax, offsetBlueMin, offsetBlueMax, offsetAlphaMin, offsetAlphaMax, transparentEdges, level</code>.</p>
<p><code>grayscale</code> - For each pixel, averages the weighted color channels and applies the result across all the color channels. This gives a more realistic monochrome effect. Object attributes: <code>action, lineIn, lineOut, opacity</code>.</p>
<p><code>invert-channels</code> - For each pixel, subtracts its current channel values - when included - from 255. Object attributes: <code>action, lineIn, lineOut, opacity, includeRed, includeGreen, includeBlue, includeAlpha</code>.</p>
<p><code>lock-channels-to-levels</code> - Produces a posterize effect. Takes in four arguments - “red”, “green”, “blue” and “alpha” - each of which is an Array of zero or more integer Numbers (between 0 and 255). The filter works by looking at each pixel’s channel value and determines which of the corresponding Array’s Number values it is closest to; it then sets the channel value to that Number value. Object attributes: <code>action, lineIn, lineOut, opacity, red, green, blue, alpha</code>.</p>
<p><code>map-to-gradient</code> - maps the colors in the supplied (complex) gradient to a grayscaled input. Object attributes: <code>action, lineIn, lineOut, opacity, useNaturalGrayscale, gradient</code>.</p>
<p><code>matrix</code> - Performs a matrix operation on each pixel’s channels, calculating the new value using neighbouring pixel weighted values. Also known as a convolution matrix, kernel or mask operation. Note that this filter is expensive, thus much slower to complete compared to other filter effects. The matrix dimensions can be set using the “width” and “height” arguments, while setting the home pixel’s position within the matrix can be set using the “offsetX” and “offsetY” arguments. The weights to be applied need to be supplied in the “weights” argument - an Array listing the weights row-by-row starting from the top-left corner of the matrix. By default all color channels are included in the calculations while the alpha channel is excluded. The ‘edgeDetect’, ‘emboss’ and ‘sharpen’ convenience filter methods all use the matrix action, pre-setting the required weights. Object attributes: <code>action, lineIn, lineOut, opacity, includeRed, includeGreen, includeBlue, includeAlpha, width, height, offsetX, offsetY, weights</code>.</p>
<p><code>modulate-channels</code> - Multiplies each channel’s value by the supplied argument value. A channel-argument’s value of ‘0’ will set that channel’s value to zero; a value of ‘1’ will leave the channel value unchanged. If the “saturation” flag is set to ‘true’ the calculation changes to start at the color range mid point. The ‘brightness’ and ‘saturation’ filters are special forms of the ‘channels’ filter which use a single “levels” argument to set all three color channel arguments to the same value. Object attributes: <code>action, lineIn, lineOut, opacity, red, green, blue, alpha, saturation</code>; pseudo-argument: <code>level</code></p>
<p><code>offset</code> - Offset the input image in the output image. Object attributes: <code>action, lineIn, lineOut, opacity, offsetRedX, offsetRedY, offsetGreenX, offsetGreenY, offsetBlueX, offsetBlueY, offsetAlphaX, offsetAlphaY; pseudo-argument: offsetX, offsetY</code>.</p>
<p><code>pixelate</code> - Pixelizes the input image by creating a grid of tiles across it and then averaging the color values of each pixel in a tile and setting its value to the average. Tile width and height, and their offset from the top left corner of the image, are set via the “tileWidth”, “tileHeight”, “offsetX” and “offsetY” arguments. Object attributes: <code>action, lineIn, lineOut, opacity, tileWidth, tileHeight, offsetX, offsetY, includeRed, includeGreen, includeBlue, includeAlpha</code>.</p>
<p><code>process-image</code> - Add an asset image to the filter process chain. The asset - the String name of the asset object - must be pre-loaded before it can be included in the filter. The “width” and “height” arguments are measured in integer Number pixels; the “copy” arguments can be either percentage Strings (relative to the asset’s natural dimensions) or absolute Number values (in pixels). The “lineOut” argument is required - be aware that the filter action does not check for any pre-existing assets cached under this name and, if they exist, will overwrite them with this asset’s data. Object attributes: <code>action, lineOut, asset, width, height, copyWidth, copyHeight, copyX, copyY</code>.</p>
<p><code>reduce-palette</code> - Reduce the number of colors in an image palette. The palette attribute can be: a Number (for the commonest colors); an Array of CSS color Strings to use as the palette; or the String name of a pre-defined palette - default: ‘black-white’. All internal color comparisons to match pixels to the closest palette color happen in the LAB color space. Dithering is applied to select the closest, or second closest, color when setting each pixel’s final output color; dithering can be random (default), or blue-noise. When calculating commonest colors, a minimum color distance can be set to get a better representative spread for images which have a predominant color (eg: images containing sky, clouds, vegetation or a plain background); calculating the commonest colors can take place in either the RGB space, or the LAB space. The Object attributes: <code>action, lineIn, lineOut, lineMix, opacity, palette, useBluenoise, minimumColorDistance, useLabForPaletteDistance</code>.</p>
<p><code>set-channel-to-level</code> - Sets the value of each pixel’s included channel to the value supplied in the “level” argument. Object attributes: <code>action, lineIn, lineOut, opacity, includeRed, includeGreen, includeBlue, includeAlpha, level</code>.</p>
<p><code>step-channels</code> - Takes three divisor values - “red”, “green”, “blue”. For each pixel, its color channel values are divided by the corresponding color divisor, rounded down or up to the integer value and then multiplied by the divisor. For example a divisor value of ‘50’ applied to a channel value of ‘120’ will give a result of ‘100’ (if clamp is set to “down” or “round”) or ‘150’ (clamp set to “up”). The output is a form of posterization. Object attributes: <code>action, lineIn, lineOut, opacity, red, green, blue, clamp</code>.</p>
<p><code>swirl</code> - For each pixel, move the pixel radially according to its distance from a given coordinate and associated angle for that coordinate. Object attributes: <code>action, lineIn, lineOut, opacity, swirls (array of arrays)</code>; pseudo-arguments (for one swirl): startX, startY, innerRadius, outerRadius, angle, easing, staticSwirls`. Note that the start paramenters can be absolute (Number) or relative (String) values, with values relative to the host Cell’s dimensions; inner and outer radius values can also be Strings relative to the host Cell’s width. Supported easing values are included in demo Filters-026.</p>
<p><code>threshold</code> - Grayscales the input then, for each pixel, checks the color channel values against a “level” argument: pixels with channel values above the level value are assigned to the ‘high’ color; otherwise they are updated to the ‘low’ color. The “high” and “low” arguments are [red, green, blue] integer Number Arrays. The convenience function will accept the pseudo-attributes “highRed”, “lowRed” etc in place of the “high” and “low” Arrays. Object attributes: <code>action, lineIn, lineOut, opacity, low, high; pseudo-arguments: lowRed, lowGreen, lowBlue, highRed, highGreen, highBlue</code>; this filter also accepts <code>lowColor</code> and <code>highColor</code> pseudo-attributes - CSS color Strings in place of the <code>lowRed, lowGreen, lowBlue, highRed, highGreen, highBlue</code> values.</p>
<p><code>tint-channels</code> - Has similarities to the SVG <feColorMatrix> filter element, but excludes the alpha channel from calculations. Rather than set a matrix, we set nine arguments to determine how the value of each color channel in a pixel will affect both itself and its fellow color channels. The ‘sepia’ convenience filter presets these values to create a sepia effect. Object attributes: <code>action, lineIn, lineOut, opacity, redInRed, redInGreen, redInBlue, greenInRed, greenInGreen, greenInBlue, blueInRed, blueInGreen, blueInBlue</code>; pseudo-arguments for the convenience method include <code>reference</code> - any valid CSS color string from which the channel values will be calculated; pseudo-arguments for the convenience method include <code>redColor, greenColor, blueColor</code> - any valid CSS color string from which the rgbIn values will be calculated.</p>
<p><code>user-defined-legacy</code> - Previous to Scrawl-canvas version 8.4.0, filters could be defined with an argument which passed a function string to a filter web worker, which the worker would then run against the source input image as-and-when required. This functionality has been removed from the new filter system. All such filters will now return the input image unchanged. Object attributes: <code>action, lineIn, lineOut, opacity</code>.</p>
<p><code>vary-channels-by-weights</code> - curves filter (for image processing tonality). The weights array must by 1024 elements long, with each element defaulting to a value of <code>1.0</code>. Object attributes: <code>action, lineIn, lineOut, opacity, weights, useMixedChannel</code>.</p>
<pre><code><span class="hljs-comment">// Example: the following code creates a filter that applies a thick red border around the entitys </span>
<span class="hljs-comment">// it is applied to; if used on a group then it will outline the outside of the group's entitys, </span>
<span class="hljs-comment">// ignoring overlaps between entitys:</span>
scrawl.<span class="hljs-title function_">makeFilter</span>({
<span class="hljs-attr">name</span>: <span class="hljs-string">'redBorder'</span>,
<span class="hljs-attr">actions</span>: [
{
<span class="hljs-attr">action</span>: <span class="hljs-string">'blur'</span>,
<span class="hljs-attr">lineIn</span>: <span class="hljs-string">'source-alpha'</span>,
<span class="hljs-attr">lineOut</span>: <span class="hljs-string">'shadow'</span>,
<span class="hljs-attr">radius</span>: <span class="hljs-number">3</span>,
<span class="hljs-attr">passes</span>: <span class="hljs-number">2</span>,
<span class="hljs-attr">includeRed</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">includeGreen</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">includeBlue</span>: <span class="hljs-literal">false</span>,
<span class="hljs-attr">includeAlpha</span>: <span class="hljs-literal">true</span>,
},
{
<span class="hljs-attr">action</span>: <span class="hljs-string">'binary'</span>,
<span class="hljs-attr">lineIn</span>: <span class="hljs-string">'shadow'</span>,
<span class="hljs-attr">lineOut</span>: <span class="hljs-string">'shadow'</span>,
<span class="hljs-attr">alpha</span>: <span class="hljs-number">1</span>,
},
{
<span class="hljs-attr">action</span>: <span class="hljs-string">'flood'</span>,
<span class="hljs-attr">lineIn</span>: <span class="hljs-string">'shadow'</span>,
<span class="hljs-attr">lineOut</span>: <span class="hljs-string">'red-flood'</span>,
<span class="hljs-attr">red</span>: <span class="hljs-number">255</span>,
},
{
<span class="hljs-attr">action</span>: <span class="hljs-string">'compose'</span>,
<span class="hljs-attr">lineIn</span>: <span class="hljs-string">'shadow'</span>,
<span class="hljs-attr">lineMix</span>: <span class="hljs-string">'red-flood'</span>,
<span class="hljs-attr">lineOut</span>: <span class="hljs-string">'colorized'</span>,
<span class="hljs-attr">compose</span>: <span class="hljs-string">'destination-in'</span>,
},
{
<span class="hljs-attr">action</span>: <span class="hljs-string">'compose'</span>,
<span class="hljs-attr">lineIn</span>: <span class="hljs-string">'source'</span>,
<span class="hljs-attr">lineMix</span>: <span class="hljs-string">'colorized'</span>,
}
],
});
</code></pre>
</div>
</li>
<li id="section-2">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-2">§</a>
</div>
<h4 id="demos">Demos:</h4>
<ul>
<li><a href="../../demo/canvas-007.html">Canvas-007</a> - Apply filters at the entity, group and cell level</li>
<li><a href="../../demo/canvas-020.html">Canvas-020</a> - Testing createImageFromXXX functionality</li>
<li><a href="../../demo/canvas-027.html">Canvas-027</a> - Video control and manipulation; chroma-based hit zone</li>
<li><a href="../../demo/packets-002.html">Packets-002</a> - Scrawl-canvas packets; save and load a range of different entitys</li>
<li><a href="../../demo/filters-019.html">Filters-019</a> - Using a Noise asset with a displace filter</li>
</ul>
</div>
</li>
<li id="section-3">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-3">§</a>
</div>
<h4 id="imports">Imports</h4>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">import</span> { constructors, cell, group, entity, asset, styles } <span class="hljs-keyword">from</span> <span class="hljs-string">'../core/library.js'</span>;
<span class="hljs-keyword">import</span> { mergeOver, removeItem, λ<span class="hljs-literal">null</span>, Ωempty } <span class="hljs-keyword">from</span> <span class="hljs-string">'../core/utilities.js'</span>;
<span class="hljs-keyword">import</span> { makeGradient } <span class="hljs-keyword">from</span> <span class="hljs-string">'./gradient.js'</span>;
<span class="hljs-keyword">import</span> baseMix <span class="hljs-keyword">from</span> <span class="hljs-string">'../mixin/base.js'</span>;</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-4">§</a>
</div>
<h4 id="filter-constructor">Filter constructor</h4>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">const</span> <span class="hljs-title class_">Filter</span> = <span class="hljs-keyword">function</span> (<span class="hljs-params">items = Ωempty</span>) {
<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">makeName</span>(items.<span class="hljs-property">name</span>);
<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">register</span>();
<span class="hljs-variable language_">this</span>.<span class="hljs-property">actions</span> = [];
<span class="hljs-variable language_">this</span>.<span class="hljs-title function_">set</span>(items);
<span class="hljs-keyword">return</span> <span class="hljs-variable language_">this</span>;
};</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-5">§</a>
</div>
<h4 id="filter-prototype">Filter prototype</h4>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">let</span> P = <span class="hljs-title class_">Filter</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span> = <span class="hljs-title class_">Object</span>.<span class="hljs-title function_">create</span>(<span class="hljs-title class_">Object</span>.<span class="hljs-property"><span class="hljs-keyword">prototype</span></span>);
P.<span class="hljs-property">type</span> = <span class="hljs-string">'Filter'</span>;
P.<span class="hljs-property">lib</span> = <span class="hljs-string">'filter'</span>;
P.<span class="hljs-property">isArtefact</span> = <span class="hljs-literal">false</span>;
P.<span class="hljs-property">isAsset</span> = <span class="hljs-literal">false</span>;</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-6">§</a>
</div>
<h4 id="mixins">Mixins</h4>
</div>
<div class="content"><div class='highlight'><pre>P = <span class="hljs-title function_">baseMix</span>(P);</pre></div></div>
</li>
<li id="section-7">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-7">§</a>
</div>
<h4 id="filter-attributes">Filter attributes</h4>
<ul>
<li>Attributes defined in the <a href="../mixin/base.html">base mixin</a>: <strong>name</strong>.</li>
<li>_<strong>Note:</strong> unlike other Scrawl-canvas factory functions, the Filter factory does not set all its default attributes as part of its constructors. The reason for this is that these attributes are often specific to just one or a few filter actions or methods; not setting these defaults help save some object memory.</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">let</span> defaultAttributes = {</pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-8">§</a>
</div>
<h5 id="how-the-filter-factory-builds-filters">How the filter factory builds filters</h5>
<p>Filter actions are defined in action objects - which are vanilla Javascript Objects collected together in the <strong>actions</strong> array. Each action object is processed sequentially by the filter engine to produce the final output for that filter.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">actions</span>: <span class="hljs-literal">null</span>,</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-9">§</a>
</div>
<p>The <strong>method</strong> attribute is a String which, in legacy filters, determines the actions which that filter will take on the image. An entity, Group or Cell can include more than one filter object in its <code>filters</code> Array. </p>
<ul>
<li>Filter factory invocations which include the <code>method</code> attribute in their argument object do not need to include an <code>actions</code> attribute; the factory will build the action objects for us.</li>
<li>When using the <code>method</code> attribute, other attributes can be included alongside it. The filter factory will automatically transpose these attributes to the action object.</li>
<li>The following Strings are valid methods: <code>'alphaToChannels', 'areaAlpha', 'binary', 'blend', 'blue', 'blur', 'brightness', 'channelLevels', 'channels', 'channelstep', 'channelsToAlpha', 'chroma', 'chromakey', 'clampChannels', 'compose', 'corrode', 'curveWeights', 'cyan', 'displace', 'edgeDetect', 'emboss', 'flood', 'gaussianBlur', 'gray', 'grayscale', 'green', 'image', 'invert', 'magenta', 'mapToGradient', 'matrix', 'matrix5', 'notblue', 'notgreen', 'notred', 'offset', 'offsetChannels', 'pixelate', 'randomNoise', 'red', 'reducePalette', 'saturation', 'sepia', 'sharpen', 'swirl', 'threshold', 'tint', 'userDefined', 'yellow'</code>.</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">method</span>: <span class="hljs-string">''</span>,</pre></div></div>
</li>
<li id="section-10">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-10">§</a>
</div>
<h5 id="how-filters-process-data">How filters process data</h5>
<p>The Scrawl-canvas filter engine can use <em><strong>multiple pathways</strong></em> to process a filter’s Array of action objects. In essence, a filter action can store the results of its work in a named cache, which can then be used by other filter actions further down the line.</p>
<ul>
<li>When Scrawl-canvas applies filters to an entity, Group or Cell it will go through the entity’s <code>filters</code> Array looking for any <code>process-image</code> actions; when it finds one it will add a snapshot of the associated asset’s current image state to the filter object (thus Cell and Noise assets are naturally dynamic).</li>
<li>Then the system sends all of the filter’s action objects over to the filter engine, alongside a snapshot of the entity, Group or Cell to be processed.</li>
<li>If the entity, Group or Cell is acting as a stencil (its <code>isStencil</code> flag has been set to true) then a snapshot of the background behind the entity/Group/Cell is sent instead of the entitys themselves.</li>
<li>When the filter engine recieves the data packet, it stores the snapshot in its <code>source</code> cache, and replicates it into the <code>work</code> object.</li>
<li>All filter actions require a <strong>lineIn</strong> string which references a cached image or snapshot. If this is not supplied, then the action will process the data stored in the <code>work</code> object.</li>
<li>Additional sources for the lineIn (or lineMix) data are <code>source</code>, which copies the original source image data and delivers it to the action; and <code>source-alpha</code> which copies the original source’s alpha channel data to each of the color channels and delivers it to the action.</li>
<li>Similarly all filter actions require a <strong>lineOut</strong> which identifies the name of a cache in which the processed data can be stored. If this is not supplied, then the action will copy the processed data back into the <code>work</code> object</li>
<li>Some filter actions - specifically <code>blend</code>, <code>compose</code> and <code>displace</code> - use two inputs, combining the data referenced by the <strong>lineIn</strong> and <strong>lineMix</strong> attribute into <strong>lineOut</strong> cache or work object.</li>
<li>When processing completes, the updated data held in the work object is returned by the filter engine, which Scrawl-canvas then uses to stamp the entity/Group/Cell into the display canvas.</li>
<li>If the entity, Group or Cell has requested that the filters applied to it be memoized, the final result will be stored in a key:value cache; the next time the entity/Group/Cell requests the filters, and it supplies a key matching one in the cache, the cached result is returned instantly</li>
<li>memoized results are time limited and expire, by default, after 1 second.</li>
</ul>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-attr">lineIn</span>: <span class="hljs-string">''</span>,
<span class="hljs-attr">lineMix</span>: <span class="hljs-string">''</span>,
<span class="hljs-attr">lineOut</span>: <span class="hljs-string">''</span>,</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<div class="sswrap ">
<a class="ss" href="#section-11">§