@Gizmosir
2016-03-22T09:00:21.000000Z
字数 10515
阅读 813
date: 2016-03-17
categories: Computer graphics
tag: [SVG, 矢量图]
博客
在上一篇中我们介绍了一部分SVG滤镜组件,在这一篇中我们将继续来介绍滤镜组件以及它们的使用方式。
在上一篇中我们介绍过色彩调节的方法,使用的是feComponentTransfer。这里我们介绍另外一个更加方便地调节色彩的方法feColorMatrix。不同的地方是feComponentTransfer使用直线/曲线来调整图像的RGBA值,而feColorMatrix不仅可以使用矩阵来调整图像的RGBA值,还可以整体地调整HSV值。
更多关于RGBA与HSV色彩系统的差别请点击这里。
色彩矩阵的含义:
<!--本例子中,我们首先生成了一个色彩矩阵滤镜,并将该滤镜应用到读取的图片上,最后我们与原图对比效果。--><svgxmlns="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 00 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度,然后将三个滤镜分别应用到读取的图像上,最后对比原图和三个滤镜处理后的图像。--><svgxmlns="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来调整图像的饱和度。
<!--本例子中首先生成一个改善饱和度的色彩矩阵滤镜,并将其应用到读取的图片上。--><svgxmlns="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的卷积矩阵滤镜,然后将滤镜应用到图像上生成最后的图像。值得注意的是卷积矩阵为拉普拉斯高通卷积,换句话说就是保留图像的高频信息,也就是边缘。--><svgxmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink" ><defs><filter id="convolve_edge"color-interpolation-filters="sRGB"><feConvolveMatrixin="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值。--><svgxmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink" ><defs><filter id="sky"><feTurbulencetype="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属性,也就是只展示后图层与前图层共用的部分。
如果将蓝色矩形换成蓝色的文本,那么我们又得到一种新的文本效果,蓝色云状!
<!--本例子代码与上个例子的代码几乎完全一致,只是修改了最后的代码将蓝色的矩形换成蓝色的文本。--><svgxmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink" ><defs><filter id="sky"><feTurbulencetype="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"将背景色定义为红色。所以通过文本后看到的是红色的背景。--><svgxmlns="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"><feTurbulencetype="fractalNoise"baseFrequency="0.013 0.003"numOctaves="1"/><feColorMatrixtype="matrix"values="0 0 0 0 11.5 0 0 0 00 0 0 0 05 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轴文字并最终生成图像效果。--><svgxmlns="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"/><feDisplacementMapin="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轴同时移动。--><svgxmlns="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"/><feDisplacementMapin="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>

接下来我们来看一个比较酷炫的例子:

<!--本例子中我们定义了一个“太阳”渐变滤镜,并将其应用到矩形中,接着我们生成一个混沌滤镜,最后将太阳滤镜根据混沌滤镜的值来做位移并生成最后的效果图像。有点复杂,结合着代码和下面的流程图多揣摩揣摩。--><svgxmlns="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"><feTurbulencetype="fractalNoise"baseFrequency="0.02"numOctaves="4"result="noise" /><feDisplacementMapin="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 ),其效果如下:


<!--本例子中,首先生成一个混沌滤镜,接着一边根据混沌滤镜来生成一个位移滤镜,另一边根据混论滤镜还生成光照滤镜,最后将两个滤镜同时应用到黄色矩形上并最终生成揉皱的黄色纸张的效果。--><svgxmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink" ><defs><filter id="recycled_paper"color-interpolation-filters="sRGB"><feTurbulencetype="fractalNoise"baseFrequency="0.04"numOctaves="5"seed="0"result="noise" /><feDisplacementMapin="SourceGraphic"in2="noise"result="displaced_image"yChannelSelector="G"xChannelSelector="R"scale="10" /><feDiffuseLightingin="noise"result="noise_with_lighting"lighting-color="rgb(233,230,215)"diffuseConstant="1"surfaceScale="2" ><feDistantLightazimuth="235"elevation="40" /></feDiffuseLighting><feCompositein="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基础技巧与进阶技巧,来制作一张属于你自己的个性名片!