svg filters html5 devconf apr 2013

Post on 13-Jul-2015

10.023 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

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

top related