61
SVG Filters: A Guide For The Perplexed 1 Michael Mullany CEO

Svg filters html5 devconf apr 2013

Embed Size (px)

Citation preview

Page 1: Svg filters   html5 devconf apr 2013

SVG Filters: A Guide For The Perplexed

1

Michael MullanyCEO

Page 2: Svg filters   html5 devconf apr 2013

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)

Page 3: Svg filters   html5 devconf apr 2013

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

Page 4: Svg filters   html5 devconf apr 2013

4

Playbook 1 + 2 Work too

Chrome Mobile Works

Source: caniuse.com

Page 5: Svg filters   html5 devconf apr 2013

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

Page 6: Svg filters   html5 devconf apr 2013

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

Page 7: Svg filters   html5 devconf apr 2013

SVG Filters - Basic Scheme

7

Input 1

Input 2

Op

Input 1 Op

Output 1

Output 2

Combine Final Output

Page 8: Svg filters   html5 devconf apr 2013

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

Page 9: Svg filters   html5 devconf apr 2013

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

Page 10: Svg filters   html5 devconf apr 2013

Example: Baked Film

10

Page 11: Svg filters   html5 devconf apr 2013

Baked Film: Example

11

1. L2A

Image 5.Composite

“Baked Film”Image

2.Blur 3.Red Light

4.Threshold

Page 12: Svg filters   html5 devconf apr 2013

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

Page 13: Svg filters   html5 devconf apr 2013

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"/>

Page 14: Svg filters   html5 devconf apr 2013

Filter Primitives

14

Page 15: Svg filters   html5 devconf apr 2013

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"/>

Page 16: Svg filters   html5 devconf apr 2013

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

Page 17: Svg filters   html5 devconf apr 2013

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

Page 18: Svg filters   html5 devconf apr 2013

type=turbulence

18

1 Octave

2 Octave

4 Octave

freq 0.05 0.1 0.5

Not very interesting by itself, but...

Page 20: Svg filters   html5 devconf apr 2013

Transformations

20

Page 21: Svg filters   html5 devconf apr 2013

ColorMatrix Types‣ 3 shorthands + 1 Matrix‣ saturate‣ huerotate‣ luminancetoAlpha

‣ luminancetoAlpha takes brightness and converts it to opacity

21

Page 22: Svg filters   html5 devconf apr 2013

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

Page 23: Svg filters   html5 devconf apr 2013

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

Page 24: Svg filters   html5 devconf apr 2013

Live demo:Color Matrix

(& alpha manipulation)

24

http://codepen.io/mullany/pen/qJCDk

Page 25: Svg filters   html5 devconf apr 2013

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

Page 26: Svg filters   html5 devconf apr 2013

Component Transfer

26

Table

Discrete

Gamma

Linear

Page 27: Svg filters   html5 devconf apr 2013

DEMO:Discrete Transforms

27

http://codepen.io/mullany/pen/oAqpF

Page 28: Svg filters   html5 devconf apr 2013

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>

Page 29: Svg filters   html5 devconf apr 2013

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

Page 30: Svg filters   html5 devconf apr 2013

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

Page 31: Svg filters   html5 devconf apr 2013

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)

?

Page 32: Svg filters   html5 devconf apr 2013

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!!

Page 33: Svg filters   html5 devconf apr 2013

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" />

      

Page 34: Svg filters   html5 devconf apr 2013

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

Page 35: Svg filters   html5 devconf apr 2013

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

Page 36: Svg filters   html5 devconf apr 2013

Lighting‣ Two types ‣ Diffuse (matte) vs. Specular (shiny)

‣ Three light sources‣ Point, distant and spot

36

Page 37: Svg filters   html5 devconf apr 2013

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

Page 38: Svg filters   html5 devconf apr 2013

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

Page 39: Svg filters   html5 devconf apr 2013

Diffuse Lighting

39

Page 40: Svg filters   html5 devconf apr 2013

Specular Lighting

40

Page 41: Svg filters   html5 devconf apr 2013

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

Page 42: Svg filters   html5 devconf apr 2013

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

Page 43: Svg filters   html5 devconf apr 2013

Compositing

43

Shorthands for compositing

+ Arithmetic(!)

k1 * A * B + k2 * A + k3 * B + k4

Source: SVG Spec

Page 44: Svg filters   html5 devconf apr 2013

DEMO:Animated Text Shadows

with Compositing(sorry, no IE)

44

http://codepen.io/mullany/details/plgDv

Page 45: Svg filters   html5 devconf apr 2013

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>

Page 46: Svg filters   html5 devconf apr 2013

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>

Page 47: Svg filters   html5 devconf apr 2013

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>

Page 48: Svg filters   html5 devconf apr 2013

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>

Page 49: Svg filters   html5 devconf apr 2013

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>

Page 50: Svg filters   html5 devconf apr 2013

50

http://www.quora.com/Instagram/How-does-Instagram-develop-their-filters

e.g. nashville filter

Page 51: Svg filters   html5 devconf apr 2013

51

Page 52: Svg filters   html5 devconf apr 2013

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>

Page 53: Svg filters   html5 devconf apr 2013

Combo Filter: Unsharp Mask

53

Take 2x Original Subtract Blur...

Sharper Version

Page 54: Svg filters   html5 devconf apr 2013

DEMO:Blur + Original Mix

(Photoshop “Unsharp Mask”

54

http://codepen.io/mullany/pen/Hsrof

Page 55: Svg filters   html5 devconf apr 2013

Out of Focus Blur

55

Page 56: Svg filters   html5 devconf apr 2013

Selective Blur

56

Spotlight + Blur + LumToAlpha +Invert

+xor w/original + composite ontop of blurred

originalhttp://codepen.io/mullany/pen/mnBqK

Page 57: Svg filters   html5 devconf apr 2013

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>

Page 58: Svg filters   html5 devconf apr 2013

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)

Page 59: Svg filters   html5 devconf apr 2013

“Why does my filter effect look clipped?”

“Why is the filter overflowing my content?”

59

Filter region defaults: -10%, -10%, 120%, 120%

Page 60: Svg filters   html5 devconf apr 2013

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

Page 61: Svg filters   html5 devconf apr 2013

61

THANK YOU!!michael aat sencha.com