Date post: | 13-Jul-2015 |
Category: |
Documents |
Upload: | michael-mullany |
View: | 9,992 times |
Download: | 1 times |
SVG Filters: A Guide For The Perplexed
1
Michael MullanyCEO
Filter Effects
2
‣ Visual transformations made before content is rendered into document‣ Color manipulations‣ Convolutions & distortions‣ Lighting effects
‣ 3 Species of Filters‣ CSS Filters (shorthand filters)‣ SVG Filters (referenceable from CSS)‣ Custom Filters (OpenGL based)
CSS Filters‣ Apply filters to any HTML content via CSS‣ Filter values are transitionable/animatable
3
Blur Invert Contrast
Grayscale Hue Rotation Opacity
Sepia Brightness Saturation
Drop shadow url(#svgfilter)
http://html5-demos.appspot.com/static/css/filters/index.htmlcredit: eric bidelman - google
4
Playbook 1 + 2 Work too
Chrome Mobile Works
Source: caniuse.com
Filters vs. Img or Canvas‣ Just like CSS, Filters help:‣ Replace images with declarative text‣ Reduce download sizes‣ Define once, apply many‣ Compact syntax
‣ Particularly useful‣ Built-in noise generator, helpful pre-built functions‣ Easy to replace noise effects for images (compress poorly)‣ Adding effects to user contributed content‣ Viewbox units means filters are dimensionless (ish)
‣ Animatable with JavaScript (IE10) & <animate> (most other browsers)
5
Y We No Use Already‣ Just available in browsers within last year!‣ Hidden rocks of silent defaults ‣ Sample code - difficult to follow
‣ Poor documentation‣ SVG Spec is often “abbreviated”‣ DOM interfaces obscure‣ Not friendly to “paste & tweak” experimentation‣ Special prizes for deciphering SVG animation
spec.‣ (XML is strict & sometimes weird)
6
SVG Filters - Basic Scheme
7
Input 1
Input 2
Op
Input 1 Op
Output 1
Output 2
Combine Final Output
Filter Syntax<defs>
<filter id= “myfilter”>...filter primitives...
</filter></defs>
standard optional SVG element props +primitiveUnits (userspace vs. bounding box)x,y ; width, height (default: -10%, -10%, 120%, 120%)filterRes (resolution of intermediate images)
Apply a filter to an element by using the filter propertyfilter = “url(#myfilter)”
8
SVG Filter Toolbox
9
Inputs Operations Lighting Combinations
Source ColorMatrix Types Composite
SourceAlpha ComponentXfer Diffuse (matte) Blend
Image ConvolveMatrix Specular (shiny) Merge
Flood (Color Fill) Morphology Sources
Turbulence (Noise) Displacement Distant Light
Background Tile | Offset Spot Light
Paint/Stroke Color GaussianBlur Point Light
Example: Baked Film
10
Baked Film: Example
11
1. L2A
Image 5.Composite
“Baked Film”Image
2.Blur 3.Red Light
4.Threshold
12
<filter id="BakedFilm">
<feColorMatrix in = "SourceGraphic" type = "luminanceToAlpha" result= "highlights"/>
<feGaussianBlur in="highlights" stdDeviation="4" result="blur"/>
<feSpecularLighting in="blur" surfaceScale="15" specularConstant=".8" specularExponent="5" lighting-color="red" result="lightmap"> <feDistantLight azimuth="45" elevation="10"/> </feSpecularLighting>
<feComponentTransfer in="lightmap" result="highlights"> <feFuncA type="table" tableValues="0 0 .5 1 1"/> </feComponentTransfer>\ <feComposite in="SourceGraphic" in2="highlights" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
</filter>
1
2
3
4
5
13
1. L2A
Image 5.Composite
“Baked Film”Image
2.Blur 3.Red Light
4.Threshold
<feColorMatrix in = "SourceGraphic" type = "luminanceToAlpha" result= "highlights"/>
<feGaussianBlur in="highlights" stdDeviation="4" result="blur"/>
<feSpecularLighting in="blur" surfaceScale="15" specularConstant=".8" specularExponent="5" lighting-color="red" result="lightmap"> <feDistantLight azimuth="45" elevation="10"/></feSpecularLighting>
<feComponentTransfer in="lightmap" result="highlights"> <feFuncA type="table" tableValues="0 0 .5 1 1"/></feComponentTransfer><feComposite in="SourceGraphic"
in2="highlights" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" result="litPaint"/>
Filter Primitives
14
Basic Inputs‣ Source: the default input = whatever the
filter has been applied to
‣ SourceAlpha: the alpha channel of the source content
‣ feImage: any image in URL format
15
<feImage xlink:href="http://somedomain.com/image.jpg" x="0" y="0" width="100%" height="100%" preserveAspectRatio="none"/>
Color Fill‣ feFlood: colored rectangle
‣ x,y, width, height, flood-color, flood-opacity
<feFlood x="5" y="10" width="100" height ="100" flood-color="rgb(24,25,250)" flood-opacity= “0.5”>
16
Turbulence‣ feTurbulence - fast noise generator ‣ Steam, rippling, marbling, woodgrain etc.
‣ Parameters: ‣ baseFrequency: X,Y (higher = more
granular)‣ numOctaves: 1,2,etc. (higher=more detail)‣ type: fractalNoise (gas) or turbulence (liquid)‣ seed: reproducible‣ stitchTiles: edge continuity in tiled results
17
type=turbulence
18
1 Octave
2 Octave
4 Octave
freq 0.05 0.1 0.5
Not very interesting by itself, but...
Add some other filters ...
19Help! Please star the webkit bug uncovered by this demohttp://code.google.com/p/chromium/issues/detail?id=225594
http://codepen.io/mullany/pen/duHbD
Transformations
20
ColorMatrix Types‣ 3 shorthands + 1 Matrix‣ saturate‣ huerotate‣ luminancetoAlpha
‣ luminancetoAlpha takes brightness and converts it to opacity
21
Full ColorMatrix
22
R->R G->R B->R A->R k1
R->G G->G B->G A->G k2
R->B G->B B->B A->B k3
R->A G->A B->A A->A k4
R
G
B
A
1
R
G
B
A
1
X =
Input Output
adds fixed offset
e.g. factor by which blue channel inputis multiplied and added to red channel output
e.g. factor by which red channel input is multiplied and added to alpha
channel output
Color Matrix Examples
23
"0.30 0.30 0.30 0 0 0.25 0.25 0.25 0 0 0.20 0.20 0.20 0 0 0.00 0.00 0.00 1 0"
"0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0.00 0.00 0.00 1 0"
"0.33 0.33 0.33 .5 0 0.00 0.00 0.00 0 0 0.00 0.00 0.00 0 0 0.00 0.00 0.00 1 0"
Sepia
Greyscale
Redden
Details(first draft): http://docs.webplatform.org/wiki/svg/elements/feColorMatrix
Live demo:Color Matrix
(& alpha manipulation)
24
http://codepen.io/mullany/pen/qJCDk
ComponentTransfer‣ Manipulate each color channel independently.
‣ 5 Types‣ identity, table, discrete, linear, gamma
‣ linear: slope*input + intercept‣ gamma: amp * (input^exponent) + offset‣ table: (a,b,c) 0->.5 mapped to a->b, .5->1
mapped to b->c.‣ discrete: (a,b,c) 0->.33 goes to a, .33->.66 goes
to b etc.
25Details (my first draft): http://docs.webplatform.org/wiki/svg/elements/feComponentTransfer
Component Transfer
26
Table
Discrete
Gamma
Linear
DEMO:Discrete Transforms
27
http://codepen.io/mullany/pen/oAqpF
DEMO:Fine-grained shadow control
28
http://codepen.io/mullany/pen/fdkmI
<filter id="f1" x="-20%" y="-20%" width="140%" height="140%"> <feGaussianBlur in="SourceAlpha" result="blurOut" stdDeviation="5"/> <feOffset in="blurOut" result="dropBlur" dx="4" dy="y"/> <feComponentTransfer in="dropBlur" result="dropBlur2"> <feFuncA id="alphaFunc" type="gamma" amplitude="2" exponent=".5" offset="0"/> </feComponentTransfer> <feComposite operator="over" in="SourceGraphic" in2="dropBlur2"/> </filter>
Convolution
1. Take values of pixels around the input pixel + current pixel value
2. Multiply by respective matrix value3. Add up the results = value of output pixel 29
0 0 0
0 1 0
0 0 0Identity
feConvolveMatrix‣ <feConvolveMatrix order= “n”
kernelMatrix= “values....”/>
‣ Optional parameters‣ Shift matrix position relative to input pixel‣ Exclude alpha channel‣ Add a divisor‣ Add a constant‣ Change edge settings
30
Patterns
31
-1 -1 -1-1 8 -1-1 -1 -1
0 -1 0-1 5 -10 -1 0
1 1 11 1 11 1 1
2 1 01 1 -10 -1 -2
1 0 00 1 00 0 1
0 -1 00 2 00 -1 0
Edges
Sharpen
Blur
Emboss
Motion Blur(linear)
?
32
<feConvolveMatrix order="11" kernelMatrix=" 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 " />
<feConvolveMatrix order="3"kernelMatrix=" 0 -1 0 -1 5 -1 0 -1 0 " />
<feConvolveMatrix order="3" kernelMatrix=" 2 1 0 1 1 -1 0 -1 -2 " />
SLOOOW!!
Morphology“Thicken & Thin”
33
erode 1px dilate 3px dilate 12px in Y
Takes min/max of each channel in
morph radius<feMorphology operator="erode" in="SourceGraphic" radius="1" />
feDisplacementMap‣ Two inputs: Source & Displacement
‣ Specify a color channel from displacement for X and Y
‣ For each pixel in Source, displace it from its original position by the color values specified in X and Y
34
Turbulence + Displacement
35
= <feTurbulence type="fractalNoise" baseFrequency=".1" numOctaves="2" result="turb"/> <feDisplacementMap in="SourceGraphic" in2="turb" scale="20" xChannelSelector="B"/>
Help! Please star this webkit bug relating to turbulence: http://code.google.com/p/chromium/issues/detail?id=163853
Lighting‣ Two types ‣ Diffuse (matte) vs. Specular (shiny)
‣ Three light sources‣ Point, distant and spot
36
Light Sources‣ Point light ‣ Looks exactly like a radial gradient in flat space‣ Specify coords of source & destination
‣ Spot light‣ Specify coords, also control focus and cone
angle
‣ Distant light‣ Azimuth (direction) and Elevation‣ Only useful with bumpmaps
37
Diffuse vs. Specular‣ Diffuse is “regular” lighting, similar to applying
semi-transparent gradients over content‣ Specify a diffuseConstant (how concentrated
the light is)‣ kernelUnitLength
‣ Specular adds shiny highlights
‣ Both can be used to simulate 3D from 2D content by generating a “bump map” (pseudo z values) from the alpha channel
38
Diffuse Lighting
39
Specular Lighting
40
Lightsource Bug help‣ Please star these webkit bugs
41
http://code.google.com/p/chromium/issues/detail?id=177623http://code.google.com/p/chromium/issues/detail?id=177624
Combinations‣ feMerge: simple z-layering
‣ feBlend: shorthand combinations‣ Normal: (=Merge)‣ Multiply: Multiply pixel values together‣ Screen: Sum - Product of pixel values‣ Darken: Use darker pixel‣ Lighten: Use lighter pixel
42
Compositing
43
Shorthands for compositing
+ Arithmetic(!)
k1 * A * B + k2 * A + k3 * B + k4
Source: SVG Spec
DEMO:Animated Text Shadows
with Compositing(sorry, no IE)
44
http://codepen.io/mullany/details/plgDv
45
<svg width="800" height="650" viewBox="0 0 800 650">
<defs> <filter id="displacement" filterUnits="objectBoundingBox"> <feTurbulence type="fractalNoise" baseFrequency=".1" numOctaves="2" result="turb"> <animate attributeType="XML" attributeName="baseFrequency" values=".1; .12; .1" dur="16s" repeatCount="indefinite"/> </feTurbulence> <feDisplacementMap in="SourceGraphic" in2="turb" scale="20" result="displace" xChannelSelector="B"/> <feGaussianBlur in="displace" result="displaceblur" stdDeviation="1"/> <feComponentTransfer in="displaceblur" result="displaceR"> <feFuncR type="discrete" tableValues=".4 .4"/> </feComponentTransfer> <feComposite operator="over" in2="SourceGraphic" in="displaceR"/> </filter>
46
<svg width="800" height="650" viewBox="0 0 800 650">
<defs> <filter id="displacement" filterUnits="objectBoundingBox"> <feTurbulence type="fractalNoise" baseFrequency=".1" numOctaves="2" result="turb"> <animate attributeType="XML" attributeName="baseFrequency" values=".1; .12; .1" dur="16s" repeatCount="indefinite"/> </feTurbulence> <feDisplacementMap in="SourceGraphic" in2="turb" scale="20" result="displace" xChannelSelector="B"/> <feGaussianBlur in="displace" result="displaceblur" stdDeviation="1"/> <feComponentTransfer in="displaceblur" result="displaceR"> <feFuncR type="discrete" tableValues=".4 .4"/> </feComponentTransfer>
<feComposite operator="in" in2="SourceGraphic" in="displaceR"/>
</filter>
47
<svg width="800" height="650" viewBox="0 0 800 650">
<defs> <filter id="displacement" filterUnits="objectBoundingBox"> <feTurbulence type="fractalNoise" baseFrequency=".1" numOctaves="2" result="turb"> <animate attributeType="XML" attributeName="baseFrequency" values=".1; .12; .1" dur="16s" repeatCount="indefinite"/> </feTurbulence> <feDisplacementMap in="SourceGraphic" in2="turb" scale="20" result="displace" xChannelSelector="B"/> <feGaussianBlur in="displace" result="displaceblur" stdDeviation="1"/> <feComponentTransfer in="displaceblur" result="displaceR"> <feFuncR type="discrete" tableValues=".4 .4"/> </feComponentTransfer>
<feComposite operator="xor" in2="SourceGraphic" in="displaceR"/>
</filter>
48
<svg width="800" height="650" viewBox="0 0 800 650">
<defs> <filter id="displacement" filterUnits="objectBoundingBox"> <feTurbulence type="fractalNoise" baseFrequency=".1" numOctaves="2" result="turb"> <animate attributeType="XML" attributeName="baseFrequency" values=".1; .12; .1" dur="16s" repeatCount="indefinite"/> </feTurbulence> <feDisplacementMap in="SourceGraphic" in2="turb" scale="20" result="displace" xChannelSelector="B"/> <feGaussianBlur in="displace" result="displaceblur" stdDeviation="1"/> <feComponentTransfer in="displaceblur" result="displaceR"> <feFuncR type="discrete" tableValues=".4 .4"/> </feComponentTransfer>
<feComposite operator="atop" in2="SourceGraphic" in="displaceR"/>
</filter>
49
<svg width="800" height="650" viewBox="0 0 800 650">
<defs> <filter id="displacement" filterUnits="objectBoundingBox"> <feTurbulence type="fractalNoise" baseFrequency=".1" numOctaves="2" result="turb"> <animate attributeType="XML" attributeName="baseFrequency" values=".1; .12; .1" dur="16s" repeatCount="indefinite"/> </feTurbulence> <feDisplacementMap in="SourceGraphic" in2="turb" scale="20" result="displace" xChannelSelector="B"/> <feGaussianBlur in="displace" result="displaceblur" stdDeviation="1"/> <feComponentTransfer in="displaceblur" result="displaceR"> <feFuncR type="discrete" tableValues=".4 .4"/> </feComponentTransfer>
<feComposite operator="out" in2="SourceGraphic" in="displaceR"/>
</filter>
50
http://www.quora.com/Instagram/How-does-Instagram-develop-their-filters
e.g. nashville filter
51
52
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" > <defs> <filter id="instagram" x="0" y="0" width="100%" height="100%" filterUnits="objectBoundingBox" primitiveUnits="userSpaceOnUse"> <!--Red curve--> <feComponentTransfer id="svg-4" result="transfer-0"> <feFuncR type="table" id="redChannel-0" tableValues="0.0586, 0.2345, 0.4206, 0.5794, 0.7690, 0.8586, 0.9379"/> </feComponentTransfer> <!--Green curve--> <feComponentTransfer id="svg-5" result="transfer-1"> <feFuncG type="table" id="greenChannel-1" tableValues="0.0000, 0.1655, 0.3620, 0.5414, 0.7138, 0.8413, 1.0000"/> </feComponentTransfer> <!--Blue curve--> <feComponentTransfer id="svg-6" result="transfer-2"> <feFuncB type="table" id="blueChannel-2" tableValues="0.1448, 0.2345, 0.3827, 0.4966, 0.6655, 0.7172, 0.7759"/> </feComponentTransfer> <!--Gamma--> <feComponentTransfer id="b1-3" result="baseimage-3"> <feFuncR type="gamma" id="redChannel-3" amplitude="1.300000" exponent="1.300000" offset="0.000000"/> <feFuncG type="gamma" id="greenChannel-3" amplitude="1.300000" exponent="1.300000" offset="0.000000"/> <feFuncB type="gamma" id="blueChannel-3" amplitude="1.300000" exponent="1.300000" offset="0.000000"/> </feComponentTransfer> <!--Soften-Sharpen--> <feGaussianBlur id="b1-4" result="blurOut-4" in="baseimage-3" stdDeviation="6"/> <feComposite id="c1-4" result="dynResult-4" in="baseimage-3" in2="blurOut-4" operator="arithmetic" k1="0" k2="1.200000" k3="-0.200000" k4="0"/> <!--Spotlight--> <feFlood id="flood-5" result="blackfield-6" x="0%" y="0%" width="100%" height="100%" result="blackfield-6" in="SourceGraphic" flood-color="#000000" flood-opacity="1"/> <feSpecularLighting id="specular-5" result="Spotlight-6" lighting-color="#FFFFFF" surfaceScale="1" specularConstant="1" specularExponent="120"> <fePointLight id="pointlight-5" x="100" y="100" z="854"/> </feSpecularLighting> <feBlend id="svg-7" result="A-6" in="blackfield-6" in2="Spotlight-6" mode="lighten"/> <feBlend id="blend-5" result="B-6" in="A-6" in2="dynResult-4" mode="multiply"/> </filter> </defs> <image id="resultImg" preserveAspectRatio="xMidYMid meet" filter="url(#instagram)" width="100%" height="100%" xlink:href="linktojpeg.jpg"/></svg>
Combo Filter: Unsharp Mask
53
Take 2x Original Subtract Blur...
Sharper Version
DEMO:Blur + Original Mix
(Photoshop “Unsharp Mask”
54
http://codepen.io/mullany/pen/Hsrof
Out of Focus Blur
55
Selective Blur
56
Spotlight + Blur + LumToAlpha +Invert
+xor w/original + composite ontop of blurred
originalhttp://codepen.io/mullany/pen/mnBqK
57
<filter id="f1" x="0%" y="0%" width="100%" height="100%"> <feDiffuseLighting result = "diffOut" diffuseConstant = "1" lighting-color = "white"> <feSpotLight id="loc" x = "50" y = "100" z = "150" pointsAtX = "200" pointsAtY = "200" pointsAtZ = "40" specularExponent ="12" limitingConeAngle="20"/> </feDiffuseLighting> <feGaussianBlur in="diffOut" result="blurSpot" stdDeviation="3"/> <feColorMatrix in="blurSpot" result="alphaMap" type="luminanceToAlpha"/> <feComponentTransfer in="alphaMap" result="invertlight"> <feFuncA type="table" tableValues="1 0 0 0"/> </feComponentTransfer>
<feComposite operator="xor" result="infocus" in2="SourceGraphic" in="invertlight"/> <feGaussianBlur in="SourceGraphic" result="outfocus" stdDeviation="6"/> <feComposite operator="over" in="infocus" in2="outfocus"/> </filter>
Edge Booogs & Support
58
Bugs & Missing Features ie moz webkitBackground as input P X X
Objects as feImage input ? X X
Fill & stroke paint as input P X X
Color space interpolation P P (not safari)
Correct lightsource positions P P X
<animate> support X P P
Filter references ? ? X
Correct default filter resolution P P (not safari)
“Why does my filter effect look clipped?”
“Why is the filter overflowing my content?”
59
Filter region defaults: -10%, -10%, 120%, 120%
Next Steps‣ Spec‣ http://www.w3.org/TR/SVG/filters.html
‣ Inkscape Filter Samples‣ http://inkscape.org
‣ Webplatform documentation‣ First draft: http://docs.webplatform.org/
wiki/svg/elements/filter
60
61
THANK YOU!!michael aat sencha.com