@Gizmosir
2016-03-22T09:00:21.000000Z
字数 10515
阅读 700
date: 2016-03-17
categories: Computer graphics
tag: [SVG, 矢量图]
博客
在上一篇中我们介绍了一部分SVG滤镜组件,在这一篇中我们将继续来介绍滤镜组件以及它们的使用方式。
在上一篇中我们介绍过色彩调节的方法,使用的是feComponentTransfer
。这里我们介绍另外一个更加方便地调节色彩的方法feColorMatrix
。不同的地方是feComponentTransfer
使用直线/曲线来调整图像的RGBA值,而feColorMatrix
不仅可以使用矩阵来调整图像的RGBA值,还可以整体地调整HSV值。
更多关于RGBA与HSV色彩系统的差别请点击这里。
色彩矩阵的含义:
<!--本例子中,我们首先生成了一个色彩矩阵滤镜,并将该滤镜应
用到读取的图片上,最后我们与原图对比效果。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<filter id="grayscale" color-interpolation-filters="sRGB">
<feColorMatrix type="matrix" in="SourceGraphic"
values=".33 .33 .33 0 0
.33 .33 .33 0 0
.33 .33 .33 0 0
0 0 0 1 0" />
</filter>
</defs>
<text x="10" y="155">Before:</text>
<image x="70" y="10" width="401" height="301"
xlink:href="colours.jpg" />
<text x="510" y="155">After:</text>
<image x="570" y="10"
width="401"
height="301"
xlink:href="colours.jpg"
style="filter:url(#grayscale)" />
</svg>
需要说明的是,在以上代码中我们将色彩矩阵声明为:
也就是将使得每个点的R、G、B值都相等。RGB色彩空间可以用下面的“色彩立方体”来表示,从图中我们能够很清晰地发现,R、G、B值都相同的点,就是图中原点(黑)到W(白)的对角线。
feColorMatrix
除了能够使用色彩矩阵外,还能用hueRotate来调整图像色彩。Hue的色彩空间如下:
<!--本例子中首先定义了三个色彩矩阵滤镜,分别把Hue旋转90度
、180度和270度,然后将三个滤镜分别应用到读取的图像上,最后
对比原图和三个滤镜处理后的图像。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<filter id="add_90" color-interpolation-filters="sRGB">
<feColorMatrix type="hueRotate" in="SourceGraphic"
values="90" />
</filter>
<filter id="add_180" color-interpolation-filters="sRGB">
<feColorMatrix type="hueRotate" in="SourceGraphic"
values="180" />
</filter>
<filter id="add_270" color-interpolation-filters="sRGB">
<feColorMatrix type="hueRotate" in="SourceGraphic"
values="270" />
</filter>
</defs>
<text x="10" y="145">Before:</text>
<image x="70" y="0" width="400" height="300"
xlink:href="brown.jpg" />
<text x="510" y="145">+90:</text>
<image x="570" y="0"
width="400"
height="300"
xlink:href="brown.jpg"
style="filter:url(#add_90)" />
<text x="10" y="600">+180:</text>
<image x="70" y="340"
width="400"
height="300"
xlink:href="brown.jpg"
style="filter:url(#add_180)" />
<text x="510" y="545">+270:</text>
<image x="570" y="340"
width="400"
height="300"
xlink:href="brown.jpg"
style="filter:url(#add_270)" />
</svg>
同样的还能使用feColorMatrix
来调整图像的饱和度。
<!--本例子中首先生成一个改善饱和度的色彩矩阵滤镜,并将其应
用到读取的图片上。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<filter id="increase_s" color-interpolation-filters="sRGB">
<feColorMatrix type="saturate" in="SourceGraphic" values="1.4"/>
</filter>
</defs>
<text x="10" y="190">Before:</text>
<image x="70" y="10" width="399" height="389"
xlink:href="woman_face.jpg" />
<text x="530" y="190">S=S*1.4:</text>
<image x="600" y="10"
width="399"
height="389"
xlink:href="woman_face.jpg"
style="filter:url(#increase_s)" />
</svg>
图像处理中一个非常重要的工具是图像卷积。使用卷积我们能够实现模糊,边缘检测等图像处理效果。SVG中当然也包含如此重要的工具:feConvolveMatrix
。
<!--本例子中,首先生成一个3x3的卷积矩阵滤镜,然后将滤镜应
用到图像上生成最后的图像。值得注意的是卷积矩阵为拉普拉斯高
通卷积,换句话说就是保留图像的高频信息,也就是边缘。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<filter id="convolve_edge"
color-interpolation-filters="sRGB">
<feConvolveMatrix
in="SourceGraphic"
kernelMatrix="0 1 0 1 -4 1 0 1 0"
order="3 3"
divisor="1"
bias="0"
preserveAlpha="true" />
</filter>
</defs>
<image width="300" height="300" xlink:href="squares.png" />
<text x="320" y="145">- after feConvolveMatrix:</text>
<image x="500" width="300" height="300"
xlink:href="squares.png"
style="filter:url(#convolve_edge)" />
</svg>
在SVG中我们常常需要用到随机值,而一个常用于产生随机数的工具就是feTurbulence
。其有两种不同的效果(fractalNoise | turbulence),如下所示:
左图为fractalNoise
效果,右图为turbulence
效果。从上图不能看出fractalNoise
稍微平衡些,turbulence
波动更大些。
题外话:混沌的名字是我自己起的,因为实在找不到翻译的地方。而实际图像效果也很像宇宙之初混沌状态不是么?
<!--本例子中,首先我们生成了一个混沌滤镜,并且与蓝色矩形复
并生成最后的图像。值得注意的是这里混沌滤镜的numOctaves为4
,也就是只有alpha值。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<filter id="sky">
<feTurbulence
type="fractalNoise"
baseFrequency="0.005"
numOctaves="4"
seed="0"
result="noise" />
<feComposite in="SourceGraphic" in2="noise" operator="in" />
</filter>
</defs>
<rect x="0" y="0"
width="800" height="600"
style="fill:blue;filter:url(#sky)" />
</svg>
值得注意的是,就如同我们之前说的那样,feTurbulence
滤镜是很多SVG实现效果的基础。同时还展示了在上一篇中我们并没有展示feComposite
的效果。需要留意的是在这里我们使用的是in
属性,也就是只展示后图层与前图层共用的部分。
如果将蓝色矩形换成蓝色的文本,那么我们又得到一种新的文本效果,蓝色云状!
<!--本例子代码与上个例子的代码几乎完全一致,只是修改了最后
的代码将蓝色的矩形换成蓝色的文本。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<filter id="sky">
<feTurbulence
type="fractalNoise"
baseFrequency="0.005"
numOctaves="4"
seed="0"
result="noise" />
<feComposite in="SourceGraphic" in2="noise" operator="in" />
</filter>
</defs>
<text x="100" y="200" font-size="150" font-family="Arial"
style="fill:blue;filter:url(#sky)" >
Blue sky text
</text>
</svg>
<!--本例子中首先生成一个混沌滤镜,然后对其进行色彩矩阵调整
,使得其红色和黄色增强,最后复合到红色背景的文本上并生成最
后的图像。值得注意的是混沌滤镜numOctaves值为1,也就是只需
要了R值。另外通过style="background-color:
red"将背景色定义为红色。所以通过文本后看到的是红色的背景。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
style="background-color: red">
<defs>
<filter id="fire"
color-interpolation-filters="sRGB">
<feTurbulence
type="fractalNoise"
baseFrequency="0.013 0.003"
numOctaves="1"
/>
<feColorMatrix
type="matrix"
values="0 0 0 0 1
1.5 0 0 0 0
0 0 0 0 0
5 0 0 0 0"
result="color_transformed" />
<feComposite in="color_transformed"
in2="SourceGraphic"
operator="out" />
</filter>
</defs>
<text x="0" y="300" font-size="350" font-family="Arial"
style="filter:url(#fire)" > Fire! </text>
</svg>
值得留意的是在这里feComposite
我们使用的是out
属性,也就是只展示前图层有而后图层没有的部分。在这个例子中,前图层是“火焰”混沌滤镜,后图层是文本。所有后图层文本的部分不显示了,也就能够透过去看到红色背景。
题外话:也许你发现我已经提及了很多种不同的文字效果,的确如此,一是因为文字效果更为常用,二是易于展示不同的滤镜效果。唯为多尝试才能了解不同的滤镜的细微差别。
在上一篇中我们介绍了偏移滤镜组件feOffset
,其功能是将图形/图像整体往X/Y轴偏移。现在我们介绍一个可以单独移动每个“像素”的滤镜组件feDisplacement
。
<!--本例子中,首先定义了一个形如上图的渐变滤镜,并该滤镜应
用到到矩形中,接着用这个渐变矩形来改变文本的Y轴文字并最终
生成图像效果。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<linearGradient id="gradient1">
<stop offset= "0" style= "stop-color:white"/>
<stop offset=".1" style= "stop-color:black"/>
<stop offset=".2" style= "stop-color:white"/>
<stop offset=".3" style= "stop-color:black"/>
<stop offset=".4" style= "stop-color:white"/>
<stop offset=".5" style= "stop-color:black"/>
<stop offset=".6" style= "stop-color:white"/>
<stop offset=".7" style= "stop-color:black"/>
<stop offset=".8" style= "stop-color:white"/>
<stop offset=".9" style= "stop-color:black"/>
<stop offset="1.0" style= "stop-color:white"/>
</linearGradient>
<rect width="800" height="400" fill="url(#gradient1)" id="gradient_area" />
<filter id="waves_filter" color-interpolation-filters="sRGB">
<feImage xlink:href="#gradient_area" result="displacement_information"/>
<feDisplacementMap
in="SourceGraphic"
in2="displacement_information"
<!--只改变了文本的Y轴方向-->
<!--由于渐变滤镜是灰度值,所以无所谓RGB哪个值-->
yChannelSelector="R"
scale="15" >
</feDisplacementMap>
</filter>
</defs>
<text x="0" y="100" font-size="80pt" font-family="Arial"
fill="darkblue" style="filter:url(#waves_filter)">
<tspan x="10">Take the</tspan>
<tspan x="60" dy="120">Star Ferry!</tspan>
</text>
</svg>
的确feDisplacementMap
由于涉及到很多东西,所以例子没有那么简单明了不易理解,那么我们就多看几个例子把。
<!--本例子与上个例子很类似,只是将线性渐变换成了径向渐变,
所以feDisplacementMap的移动也变成了X轴Y轴同时移动。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<radialGradient id="gradient1">
<stop offset= "0" style= "stop-color:white"/>
<stop offset=".1" style= "stop-color:black"/>
<stop offset=".2" style= "stop-color:white"/>
<stop offset=".3" style= "stop-color:black"/>
<stop offset=".4" style= "stop-color:white"/>
<stop offset=".5" style= "stop-color:black"/>
<stop offset=".6" style= "stop-color:white"/>
<stop offset=".7" style= "stop-color:black"/>
<stop offset=".8" style= "stop-color:white"/>
<stop offset=".9" style= "stop-color:black"/>
<stop offset="1.0" style= "stop-color:white"/>
</radialGradient>
<rect width="1000" height="450" fill="url(#gradient1)" id="gradient_area" />
<filter id="fracture_filter" color-interpolation-filters="sRGB">
<feImage xlink:href="#gradient_area" result="displacement_information"/>
<feDisplacementMap
in="SourceGraphic"
in2="displacement_information"
<!--在X轴和Y轴上发送位移-->
<!--由于渐变滤镜是灰度值,所以无所谓RGB哪个值-->
xChannelSelector="R"
yChannelSelector="R"
scale="15" >
</feDisplacementMap>
</filter>
</defs>
<text x="0" y="100" font-size="80pt" font-family="Arial"
style="filter:url(#fracture_filter)">
<tspan x="60"> Fractured</tspan>
<tspan x="30" dy="90">Information</tspan>
</text>
</svg>
接下来我们来看一个比较酷炫的例子:
<!--本例子中我们定义了一个“太阳”渐变滤镜,并将其应用到矩形
中,接着我们生成一个混沌滤镜,最后将太阳滤镜根据混沌滤镜的
值来做位移并生成最后的效果图像。有点复杂,结合着代码和下面
的流程图多揣摩揣摩。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
style="background-color: black" >
<defs>
<filter id="explode"
color-interpolation-filters="sRGB">
<feTurbulence
type="fractalNoise"
baseFrequency="0.02"
numOctaves="4"
result="noise" />
<feDisplacementMap
in="SourceGraphic"
in2="noise"
scale="150"
<!--其实RGB值如何用的无所谓-->
xChannelSelector="R"
yChannelSelector="B" />
</filter>
<radialGradient id="sun_gradient" cx="400" cy="400"
r="350" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="red"/>
<stop offset="0.1" stop-color="red"/>
<stop offset="0.4" stop-color="yellow"/>
<stop offset="0.8" stop-color="orange"/>
<stop offset="1" stop-color="lightorange" />
</radialGradient>
</defs>
<!--这里生成一个矩形,然后先用“太阳”渐变滤镜填充,然后在使用由混沌滤镜生成的位移滤镜-->
<rect x="0" y="0" height="800" width="800"
fill="url(#sun_gradient)" filter="url(#explode)"/>
</svg>
在显示生活中,光照是影响图片效果的很重要的部分。毫无例外的SVG也包含不同的光照滤镜组件( feDiffueseLighting | feSpecularLighting | feDistantLight | fePointLight | feSpotLight ),其效果如下:
<!--本例子中,首先生成一个混沌滤镜,接着一边根据混沌滤镜来
生成一个位移滤镜,另一边根据混论滤镜还生成光照滤镜,最后将
两个滤镜同时应用到黄色矩形上并最终生成揉皱的黄色纸张的效果。-->
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<defs>
<filter id="recycled_paper"
color-interpolation-filters="sRGB">
<feTurbulence
type="fractalNoise"
baseFrequency="0.04"
numOctaves="5"
seed="0"
result="noise" />
<feDisplacementMap
in="SourceGraphic"
in2="noise"
result="displaced_image"
yChannelSelector="G"
xChannelSelector="R"
scale="10" />
<feDiffuseLighting
in="noise"
result="noise_with_lighting"
lighting-color="rgb(233,230,215)"
diffuseConstant="1"
surfaceScale="2" >
<feDistantLight
azimuth="235"
elevation="40" />
</feDiffuseLighting>
<feComposite
in="displaced_image"
in2="noise_with_lighting"
result="combined_result"
<!--自定义两个滤镜结合的方法-->
operator="arithmetic"
k1="1.7" />
</filter>
</defs>
<rect x="100" y="100"
width="600" height="400"
style="fill:#ffd42a;filter:url(#recycled_paper)" />
</svg>
那么基本上我们就将所有的滤镜组件都介绍了一遍,我相信你对不同滤镜的效果和使用方法也有个大概的了解。当然这么多滤镜肯定是无法一下子都掌握的,唯有自己多动手试试。下篇我将结合之前介绍过的SVG基础技巧与进阶技巧,来制作一张属于你自己的个性名片!