SVG Scalable Vector Graphics

SVG 濾鏡元件之一

SVG 有一組豐富的選項來處理圖片(繪製的或位元圖的)。 這些是附加到 物件的選項:既多樣又在某些情況下複雜的技巧。

定義濾鏡

先在<defs></defs>�媕Y,加入<filter></filter>的標籤,然後給它一個 id 作為識別,接著就是要在filter�媕Y放入濾鏡。 在此之前,filter 除了 x、y、width、height 幾個基本屬性外,也幾個比較特別的屬性需要設定:
<defs>
  <filter id="id名" x="0" y="0" width="100%" height="100%" filterUnits="userSpaceOnUse">
    濾鏡
  </filter>
</defs>

濾鏡列表

SVG 中可用的濾鏡元件有:

<feGaussianBlur>

所有 SVG 濾鏡都在 <defs> 元件中定義。 <defs> 元件是定義的縮寫,包含特殊元件(例如濾鏡)的定義。

<filter> 元件用於定義 SVG 濾鏡。 <filter> 元件有一個必需的 id 屬性來標識濾鏡。 然後圖形指向要使用的濾鏡。

<svg height="110" width="110">
  <defs>
    <filter id="f1" x="0" y="0">
      <feGaussianBlur in="SourceGraphic" stdDeviation="15" />
    </filter>
 </defs>
  <rect width="90" height="90" stroke="blue"
          stroke-width="3" fill="blue" filter="url(#f1)" />
  Sorry, your browser does not support inline SVG.
</svg>
Sorry, your browser does not support inline SVG.
注意到上面的 SVG 沒有定義 viewbox, 並且使用 0 的寬度和高度。那是因為使用那個特定的 SVG 只定義濾鏡,所以不希望它佔用任何視覺 頁面上的空間。

<feFlood>

SVG 濾鏡基元用 flood-color 和 flood-opacity 定義的顏色和不透明度填充矩形區域。
  <defs>
    <filter id="floodFilter" filterUnits="userSpaceOnUse">
      <feFlood x="50" y="50" width="100" height="100"
          flood-color="green" flood-opacity="0.5"/>
    </filter>
  </defs>
  <use style="filter: url(#floodFilter);"/>

<feOffset>

這用於在濾鏡內移動一大塊圖像,通常是 SourceGraphic 或 BackgroundImage,以便稍微重新對齊。 以下投影結果是使用 <feOffset> 完成的。 我們繼續接收圖像並應用模糊濾鏡。 然後將該模糊圖像偏移(向右 5 個像素和向下 5 個像素) ,並存儲為結果“B”。 然後將結果 B 合併到原始 SourceGraphic 下以創建效果。
<svg height="120" width="120">
  <defs>
    <filter id="f2" x="0" y="0">
      <feGaussianBlur stdDeviation="5" />
      <feOffset dx="5" dy="5" />
    </filter>
  </defs>
  <rect width="90" height="90" fill="grey" filter="url(#f2)" />   // B
  <rect width="90" height="90" fill="yellow" stroke="black" />    // 原始圖像
  Sorry, your browser does not support inline SVG.
</svg>
Sorry, your browser does not support inline SVG.

組合濾鏡基元

有多種組合濾鏡基元(primitive)的方法。 一種方法是將一個濾鏡基元 F2 用於一個物件,然後將該物件嵌套在應用了濾鏡 F2 的 中。
<filter id="F1">
       <someFilterPrimitive1 />
</filter>

<filter id="F2">
       <someFilterPrimitive2 />
</filter>

<g filter="url(#F2)">
  <rect height="20%" width="15%" filter="url(#F1)"/>
</g>
通過在單個 元件中將濾鏡基元鏈接在一起,可以獲得等效的結果,如下所示:
<filter id="Fs">
       <someFilterPrimitive1/>
       <someFilterPrimitive2/>
</filter>

<rect height="20%" width="15%" filter="url(#Fs)"/>

除了能夠順序地將不同濾鏡基元的結果鏈接在一起,其中每個連續濾鏡將前一個過濾器的輸出(稱為“result”)作為其輸入(稱為“in”), 還可以以更複雜的順序組合濾鏡。

首先,考慮濾鏡處理多種效果的預設方式。 通常, <filter> 中的第一個基元接收“SourceGraphic”作為輸入的,即濾鏡基元一一應用到的元件。

例如,如果我們定義

  <rect filter=”url(#Fs)” … />
  
那個矩形被認為是濾鏡“Fs”的 SourceGraphic。 連續的每個基元(FP1、FP2、…FPk)都將前一個濾鏡的輸出“result”當作它的輸入"in"。

<feMerge>

feMerge 濾鏡允許並行組合濾鏡,而不是串行組合(如前面的示例)。 feMerge 提供了一種臨時存儲每個濾鏡輸出的方法。 一旦創建了多個圖層並將其存儲為不同圖元的結果,就可以將它們按從下到上的順序放置在畫布上。
<rect x="0" y="0" height="100%" width="100%" fill="white"/>
<filter id="offset"  x="-20%" y="-10%" height="130%" width="240%">
  <feGaussianBlur stdDeviation="10"/>
  <feOffset dx="20" dy="15" result="B">
  </feOffset>
  <feMerge>
    <feMergeNode in="B"/>
    <feMergeNode in="SourceGraphic"/>
  </feMerge>
</filter>

<g filter="url(#offset)">
  <image x="25%" y="3%" xlink:href="../svg/p2.jpg"  height="100%" width="100%"/>
</g>

例題:陰影動畫

<feImage>

嵌入圖檔,嵌入的圖當將會顯示成點陣圖(bitmap),即使嵌入SVG也一樣。
正如 feFlood 允許將彩色矩形引入濾鏡一樣,feImage 允許將矩形點陣圖引入濾鏡。
<feImage xlink:href="../svg/mdn_logo_only_color.png" />

<feTile>

<feFlood> 之於 <rect>,正如 <feImage> 之於 <image>。 同樣,<feTile> 直接類似於 <pattern>。 它允許我們將重複的圖像模式帶入過濾器設備,以便我們可以使用它來創建效果。 以下是 的簡單使用:
<rect x="0" y="0" height="100%" width="100%" fill="purple"/>
<filter id="T" filterUnits="objectBoundingBox" x="0" y="0"
    height="100%" width="100%" >
  <feImage xlink:href="p2.jpg" result="one"
              x="0" y="15" width="50" height="50"/>
  <feFlood x="45" y="0" width="10" height="70"
        flood-color="cyan" result="two"/>
  <feFlood x="25" y="18" width="50" height="10" flood-color="yellow"
        flood-opacity=".5" result="three" />
  <feMerge>
      <feMergeNode in="one"/>
      <feMergeNode in="two"/>
      <feMergeNode in="three"/>
  </feMerge>
  <feTile/>
</filter>
<rect x="0" y="0" height="80%" width="50%" filter="url(#T)" />

<feColorMatrix>

feColorMatrix 基元允許重新定義圖像中的顏色,基於將每個像素的 RGB 和 alpha 級別乘以數字係數的能力。 在更複雜的情況下,用戶可以指定一個由 20 個係數(4 x 5)組成的完整矩陣,以乘以表示給定像素顏色值的 1 x 4 向量。
| R' |     | a00 a01 a02 a03 a04 |   | R |
| G' |     | a10 a11 a12 a13 a14 |   | G |
| B' |  =  | a20 a21 a22 a23 a24 | * | B |
| A' |     | a30 a31 a32 a33 a34 |   | A |
| 1  |     |  0   0   0   0   1  |   | 1 |
在更簡單的情況下,預定義矩陣與特殊標誌(例如“saturate”、“hueRotate”或“luminanceToAlpha”)相關聯。 這意味著可以簡單地指定標誌之一來執行指示的操作。
<svg height="440" width="440" xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
<filter id="F">
 <feColorMatrix type="saturate" values="3" />
</filter>
</defs>
<image x="25%" y="0" width="25%" height="35%" xlink:href="p2.jpg"/>
<image x="50%" y="0" width="25%" height="35%" xlink:href="p2.jpg"
      filter="url(#F)"/>
</svg>
feColorMatrix 是使用矩陣來影響顏色的每個通道(基於RGBA):
<filter>
     <feColorMatrix
      type="matrix"
      values="R 0 0 0 0
              0 G 0 0 0
              0 0 B 0 0
              0 0 0 A 0 "/>
      </feColorMatrix>
</filter>

每一列(row)的和就是該通道的值,最後一個值是一個乘數。

著色
可以遺漏或混合顏色通道給圖像著色,像下面這樣:紅色和藍色混成品紅色(magenta)。
<filter id="magenta" x="0%" y="0%" width="100%" height="100%">
       <feColorMatrix type="matrix" in="SourceGraphic"
       values=
               "1   0  0  0  0
                0   0  0  0  0
                0   0  1  0  0
                0   0  0  0  0
       "/>
</filter>
<image x="5%" y="0%" xlink:href="../svg/three.jpg" height="50%" width="30%"/>
<image x="5%" y="50%" xlink:href="../svg/three.jpg"
        filter="url(#magenta)" height="50%" width="30%"/>

當一個顏色值消失後,會使用其他兩個值取而代之。
比如,沒有green顏色通道就會沒有white、cyan或yellow。
其實他們並沒有消失,只不過他們的亮度值(或alpha)尚未觸及。

ALPHA值
我們可以通過 alpha(第四行)來突出陰影和亮度。第四列受alpha通道影響,而第四行將影響每個通道的亮度值,如:
<filter id="alpha" x="0%" y="0%" with="100%" height="100%">
       <feColorMatrix type="matrix" in="SourceGraphic"
       values=
               "1   0  0  0   0
                0   1  0  0   0
                0   0  1  0   0
                0   0  0  1   0  "/>
</filter>
吹出通道
我們也可以通過第四列的個人通道影響整個alpha通道。
示例中有一個藍色的天空,可以將藍色的天空變成白色,如下:
<filter id="elim-blue" x="0%" y="0%" width="100%" height="100%">
       <feColorMatrix type="matrix" in="SourceGraphic"
       values=
               "1   0  0  0  0
                0   1  0  0  0
                0   0  1  0  0
                0   0 -2  1  0
       "/>
</filter>
變亮和變暗
通過將RGB值每個通道的值設置成小於1,可以創建一個變暗效果,反之,將每個通道值設置成大於1可以創建一個變亮效果。下圖能清晰的闡述這一切:
<filter id="lighten">
  <feColorMatrix type="matrix"
    values="1.5  0   0   0   0
             0 1.5   0   0   0
             0   0 1.5   0   0
             0   0   0   1   0 "/>
</filter>
灰度
通過在一列中僅接受一個陰影的像素值,可以創建灰度效果。例如
<filter id="gray">
  <feColorMatrix type="matrix"
    values="1   0   0   0   0
            1   0   0   0   0
            1   0   0   0   0
            0   0   0   1   0 "/>
</filter>

第一行的三個 1 移到第二或三列,也有類似效果。

綜合
feColorMatrix 的真正力量在於它能夠混合通道並將許多這些概念組合成新的圖像效果。
<filter id="peachy">
  <feColorMatrix type="matrix"
    values="1   0   0   0   0
            0  .5   0   0   0
            0   0   0  .5   0
            0   0   0   1   0 "/>
</filter>
在正常 Alpha 通道上使用紅色通道,在一半強度下應用綠色,在較暗的 Alpha 通道上應用藍色,但不在其原始顏色位置。 這種效果在陰影中為我們提供了深藍色,在高光和中間色調中混合了紅色和半綠色。 如果我們回憶一下紅色 + 綠色 = 黃色,紅色 + (綠色/2) 會更像珊瑚色。
<filter id="lime">
  <feColorMatrix type="matrix"
    values="1   0   0   0   0
            0   2   0   0   0
            0   0   0  .5   0
            0   0   0   1   0 "/>
</filter>
在該段中,我們使用紅色、溢出的綠色和藍色的正常像素色調,沒有其原始色調像素,但應用於陰影中。 同樣,我們看到陰影中的深藍色, 由於紅色 + 綠色 = 黃色,紅色 + (綠色 * 2) 在高光中更像是黃綠色。

在下面的示例中,將圖像從標準 RGB 轉換為部分透明。使用圖像的最暗部分,以便底層顏色透出。 在這種情況下,使用作為濾鏡的一部分創建的“黃色”。

<svg xmlns="http://www.w3.org/2000/svg"
	xmlns:xlink="http://www.w3.org/1999/xlink">
<filter id="twoF" x="0%" y="0%" width="100%" height="100%">
       <feFlood  flood-color="yellow" result="A"/>
       <feColorMatrix type="matrix" in="SourceGraphic" result="B"
       values=
               "1   0  0  0  0
                0   1  0  0  0
                0   0  1  0  0
                1   1  1  0  0
       "/>
       <feMerge>
              <feMergeNode in="A"/>
              <feMergeNode in="B"/>
       </feMerge>
</filter>
<image x="5%" y="20%" xlink:href="p2.jpg" filter="url(#twoF)"
    height="50%" width="30%"/>
</svg>

參考資料

<feConvolveMatrix>

濾鏡feConvolveMatrix定義一個 n × n 矩陣(通常 n 為奇數),其中矩陣的中心單元是指像素本身,而矩陣中它的上方、左側、下方和右側的單元, 參考到該像素的上方、左側、下方和右側的像素。 矩陣中的數字係數定義了每個相鄰像素在計算該像素的新顏色值時的權重。 在最簡單的情況下,矩陣
      0 0 0
      0 1 0
      0 0 0
不影響任何圖像。

<feConvolveMatrix> 屬性

  • <order>
    定義我們作用的圖格有幾格 ( 也就是矩陣要多大 ),預設是 3 ,也就是 3x3 的矩陣。
  • kernelMatrix <feConvolveMatrix> 中最關鍵的屬性,就是矩陣 kernelMatrix 的值,如下所示:
    <filter id="edge">
           <feConvolveMatrix order="3"
           kernelMatrix="
                -1  -1  -1
                -1   7  -1
                -1  -1  -1
           " />
    </filter>
    <image id="M4" x="100" xlink:href="../svg/p2.jpg"
        width="150" height="175"
        filter="url(#edge)" />
    
    上述內容誇大那些與其相鄰像素非常不同的像素,因為每個像素相鄰像素的權重為負。
  • divisor
    這個數字預設值為矩陣的總和。
  • bias
    最後出來結果的偏移量,預設值為 0。
  • targetX、targetY
    目標像素的中心位置,最左邊與最上面為 0,最右邊和最下面則是整個矩陣的大小,預設都是在中心點的位置。
  • edgeMode = "duplicate | wrap | none"
    none 就是不會重複,duplicate 就是進行鏡像地重複,wrap 就是進行單純的重複。
  • kernelUnitLength
    預設只有一個數值,也可以填寫兩個數值,分別是 dx 和 dy,這個屬性讓原本作用只有一個像素的內核,可以伸縮擴展。
  • preserveAlpha = "false | true"
    預設值為 false ,表示 alpha 色版將也會一併進行矩陣運算,如果設為 true,將只會用於 RGB 色版。

浮彫示例

  <defs>
      <filter id="emboss">
        <feConvolveMatrix  order="3"
            kernelMatrix="
                  -2 -1  0
                  -1  1  1
                   0  1  2"
            edgeMode="none">
        </feConvolveMatrix>
      </filter>
  </defs>

更多示例一:提取邊緣--浮彫

<filter id="filter1" x="0" y="0" width="100%" height="100%">
    <feConvolveMatrix order="5 5" preserveAlpha="true"
       kernelMatrix="
          -1 0 0 0 0
          0 -2 0 0 0
          0  0 3 0 0
          0  0 0 0 0
          0  0 0 0 0" />
</filter>

更多示例二:提取邊緣--紅色浮彫

使用 feConvolveMatrix 造成浮彫效果,再用 feConvolveMatrix 僅保留紅色。

<filter id="filter1" x="0" y="0" width="100%" height="100%">
    <feConvolveMatrix preserveAlpha="true"
        kernelMatrix="-2 -2 -2
                      -2 16 -2
                      -2 -2 -2" />
    <feColorMatrix type="matrix"
        values="0  1  0  0  0
               0  0  0  0  0
               0  0  0  0  0
               0  0  0  1  0" />
</filter>

更多示例三:提取邊緣--藍色浮彫

將 feColorMatrix 換成下列數值,即可換成僅保留藍色。

    <feColorMatrix type="matrix"
        values="0  0   0  0  0
                0  .95 0  0  0
                0  1   0  0  0
                0  0   0  1  0" />

參考資料

關於濾鏡 feConvolveMatrix 詳細解說,見 filter:feConvolveMatrix
kernelMatrix 的影像處理, 詳見 filter:feConvolveMatrix
更多示例見 svg中feConvolveMatrix

<feComponentTransfer>

feComponentTransfer 包含四個元素,分別是:feFuncR、feFuncG、feFuncB、feFuncA,也就是可以針對紅綠藍與 alpha 色版進行獨立調整,調整的 type 分為五種,分別是:identity、table、discrete、linear、gamma。
 <defs>
   <filter id="table">
    <feComponentTransfer>
     <feFuncG type="table" tableValues="0.0 0.15 0.4 1.0" />
    </feComponentTransfer>
   </filter>
 </defs>
 <image x="0" y="0" width="300" height="200" xlink:href="three.jpg" />
 <image x="0" y="200" width="300" height="200"
       xlink:href="three.jpg" filter="url(#green)" />

右上圖是原圖,右下圖是調整顏色後的圖像。

此 table 設置了四個關鏈點 0.0 0.15 0.4 1.0 ,區隔出三個區間。輸出和輸入的關係如示:
 輸入         輸出
0-0.33	    0.0-0.15
0.33-0.66   0.15-0.4
0.66-1	    0.4 1.0
輸入分成三等分區間,分別映對到 table 的三個區間。

色度反轉

<filter id="inverse">
 <feComponentTransfer>
   <feFuncR type="table" tableValues="1 0" />
   <feFuncG type="table" tableValues="1 0" />
   <feFuncB type="table" tableValues="1 0" />
 </feComponentTransfer>
</filter>
使用 type='table' 反轉色度範圍。 將正常範圍從 0 到 1 並映射到一個新的分佈:0-> 1 和 1-> 0,以及所有介於兩者之間,對於圖像的三個通道中的每一個。

<feComponentTransfer> -- discrete

輸入分成的等分區間,分別映對到單一數值。例如下例中,
feFuncB 設有兩點 0.0 和 0.6,輸入 0-0.5 映到 0.0,0.5-1 映到0.6。
<defs>
    <filter id="discrete" filterUnits="userSpaceOnUse"
              x="0" y="200" width="300" height="200">
      <feComponentTransfer>
        <feFuncR type="discrete" tableValues="0.0 1.0 1.0 1.0" />
        <feFuncG type="discrete" tableValues="0.0 0.5 0.5 0.9" />
        <feFuncB type="discrete" tableValues="0.0 0.6" />
      </feComponentTransfer>
    </filter>
</defs>
<image x="0" y="0" width="300" height="200" xlink:href="three.jpg" />
<image x="0" y="200" width="300" height="200"
                xlink:href="three.jpg" filter="url(#discrete)" />

右上圖是原圖,右下圖是調整顏色後的圖像。

再舉一例
<filter id="paint" filterUnits="userSpaceOnUse"
      x="0" y="200" width="300" height="250">
    <feComponentTransfer>
        <feFuncR type="discrete" tableValues="0 .5 1 1"/>
        <feFuncG type="discrete" tableValues="0 .5 1"/>
        <feFuncB type="discrete" tableValues="0"/>
     </feComponentTransfer>
</filter>

此選項將區間 [0,1] 中的紅色值映射到以下三個值之一:

(0 到 .25) -> 0; (.25 到 .50) -> .5; (.50 到 .75 和 .75 到 1.0) -> 1。

綠色通道前段、中段和後段,分別映射到 0%、50% 或 100% 綠色。
藍色通道(在此特定圖像中相對微不足道)被抑制為黑色(完全消除其效果)。
原圖像沒有 alpha 通道(每點都是不透明的),因此不需要修改該通道。

<feComponentTransfer> -- linear

線性變化: 輸出 = k*輸入 + b,k 是斜率(slope),b 是截距(intercept)。
下例綠色輸出為 0。
<defs>
  <filter id="linear" filterUnits="objectBoundingBox"
        x="0%" y="0%" width="100%" height="100%">
    <feComponentTransfer>
      <feFuncR type="linear" slope="1" intercept="0" />
      <feFuncG type="linear" slope="0" intercept="0" />
      <feFuncB type="linear" slope="1" intercept="0" />
      </feComponentTransfer>
   </filter>
</defs>
<image x="0" y="0" width="300" height="200" xlink:href="three.jpg" />
<image x="0" y="200" width="300" height="200"
   xlink:href="three.jpg" filter="url(#Linear)" />

<feComponentTransfer> -- gamma

曲線變化: 需設定三個參數amplitude(振幅),exponent(指數) 和 offset(偏差)。

輸出 = amplitude * pow(輸入,exponent) + offset

<defs>
  <filter id="Gamma" filterUnits="objectBoundingBox"
          x="0%" y="0%" width="100%" height="100%">
    <feComponentTransfer>
      <feFuncR type="gamma" amplitude="2" exponent="3" offset="0" />
      <feFuncG type="gamma" amplitude="2" exponent="2" offset="0" />
      <feFuncB type="gamma" amplitude="2" exponent="1" offset="0" />
    </feComponentTransfer>
  </filter>
</defs>
<image x="0" y="0" width="300" height="200" xlink:href="three.jpg" />
<image x="0" y="200" width="300" height="200"
        xlink:href="three.jpg" filter="url(#Gamma)" />

feComponentTransfer 參考資料

==>svg-filters2

參考資料

  1. SVG Filter Play
  2. Filter Effects in SVG
  3. svg filter
  4. SVG 完整教學 31 天
  5. 一次搞懂SVG中所有常用的濾鏡
  6. why-the-svg-filter-is-awesome
  7. The 10 Best SVG Filter Resources & Tutorials
  8. 強大的 SVG 濾鏡
  9. svg-filter-shadow-css-blur
  10. fediffuselighting
  11. SVG feTurbulence濾鏡深入介紹
  12. SVG fedisplacementmap濾鏡深入介紹
  13. SVG fedisplacementmap濾鏡深入介紹
  14. w3 SVG 1.1
  15. SVG 筆記