iT邦幫忙

DAY 27
1

SVG 30 天 ~ 就要醬玩系列 第 27

Day27 - SVG filter - feComponentTransfer

feComponentTransfer 是針對圖像中每一個像素,利用公式的計算,進行亮度、對比...等調整,其實就有點類似 Photoshop 裏頭的「曲線」調整模式,我們可以利用調整線條的斜率、或是曲線的公式,對圖片進行更細緻的調整,只是在 photoshop 裏頭已經幫我們做了視覺介面的處理,在 SVG 裏頭則是必須要自己手動輸入相關數值。( oxxostudio.tw 同步發表:SVG 研究之路 (15) - filter - feComponentTransfer )

feComponentTransfer 包含四個元素,分別是:feFuncR、feFuncG、feFuncB、feFuncA,也就是可以針對紅綠藍與 alpha 色版進行獨立調整,調整的 type 分為五種,分別是:identity、table、discrete、linear、gamma,五種調整 type 的對照公式可以參考 W3C 的詳細說明

首先看到 table,table 屬性主要是將我們所輸入的區塊,重新填入原本對照的色彩梯度區塊當中 ( 如下圖 ),就可以產生不同色彩梯度的效果。

我們也可以利用 table 屬性來讓一張圖片有不同風格的變化 :

<svg width="300" height="500">
  <defs>
    <filter id="table" filterUnits="userSpaceOnUse" x="0" y="200" width="300" height="200">
      <feComponentTransfer>
        <feFuncR type="table" tableValues="0.0 0.7 0.9 1.0"/>
        <feFuncG type="table" tableValues=".2 0.7 0.9 1.0"/>
        <feFuncB type="table" tableValues=".2 0.7 0.9 1.0"/>
      </feComponentTransfer>
    </filter>
  </defs>
  <image x="0" y="0" width="300" height="200" xlink:href="圖片網址" />
  <image x="0" y="200" width="300" height="200" xlink:href="圖片網址" filter="url(#table)"  />
</svg>

再來看到 discrete,從字面翻譯就是「離散」,也就是當我們列出一個數字的陣列,就會採用這個陣列的數字直接填入該色彩梯度內,造成沒有漸層的情形,如下圖

也因為少了很多顏色,所產生的圖片效果也頗特殊的:

<svg width="300" height="500">
  <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="圖片網址" />
  <image x="0" y="200" width="300" height="200" xlink:href="圖片網址" filter="url(#discrete)"  />
</svg>

至於 linear 和 gamma 就簡單多了,linear 就是調整直線的斜率,和 linear 有關的參數有兩個,一個是 slope,也就斜率,預設值為 1,另外一個是 intercept,預設值為 0 ( linear 的公式為:C' = slope * C + intercept ) 了解了之後,我們就可以很輕鬆的對漸層當中的顏色作調整。

<svg width="8cm" height="100%" viewBox="0 0 800 800">
    <linearGradient id="MyGradient" gradientUnits="userSpaceOnUse"
            x1="100" y1="0" x2="600" y2="0">
      <stop offset="0" stop-color="#000000" />
      <stop offset=".3" stop-color="#00ff00" />
      <stop offset=".6" stop-color="#0000ff" />
      <stop offset="1" stop-color="#ff0000" />
    </linearGradient>
    <filter id="Linear" filterUnits="objectBoundingBox" 
            x="0%" y="0%" width="100%" height="100%">
      <feComponentTransfer>
        <feFuncR type="linear" slope="0" intercept="0"/>
        <feFuncG type="linear" slope="0" intercept="0"/>
        <feFuncB type="linear" slope="1" intercept="0"/>
      </feComponentTransfer>
    </filter>
  </defs>
    <rect x="100" y="420" width="600" height="60" fill="url(#MyGradient)" />
    <rect x="100" y="490" width="600" height="60" fill="url(#MyGradient)" filter="url(#Linear)" />
</svg>

<svg width="300" height="500">
  <defs>
    <filter id="Linear" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
      <feComponentTransfer>
        <feFuncR type="linear" slope="0" intercept="0"/>
        <feFuncG type="linear" slope="1" intercept="0"/>
        <feFuncB type="linear" slope="1" intercept="0"/>
      </feComponentTransfer>
    </filter>
  </defs>
  <image x="0" y="0" width="300" height="200" xlink:href="圖片網址" />
  <image x="0" y="200" width="300" height="200" xlink:href="圖片網址" filter="url(#Linear)"  />
</svg>

最後是 gamma ,gamma 就是調整指數曲線的數值,與 photoshop 裏頭調整圖片曲線有異曲同工之妙,當然還是必須得手動輸入一些數值就是了,gamma 的公式為:C' = amplitude * pow(C, exponent) + offset,因此就具有三個參數:amplitude、exponent、offset。

<svg width="8cm" height="100%" viewBox="0 0 800 800">
    <linearGradient id="MyGradient" gradientUnits="userSpaceOnUse"
            x1="100" y1="0" x2="600" y2="0">
      <stop offset="0" stop-color="#000000" />
      <stop offset=".3" stop-color="#00ff00" />
      <stop offset=".6" stop-color="#0000ff" />
      <stop offset="1" stop-color="#ff0000" />
    </linearGradient>
    <filter id="Gamma" filterUnits="objectBoundingBox" 
            x="0%" y="0%" width="100%" height="100%">
      <feComponentTransfer>
        <feFuncR type="gamma" amplitude="2" exponent="5" offset="0"/>
        <feFuncG type="gamma" amplitude="2" exponent="3" offset="0"/>
        <feFuncB type="gamma" amplitude="2" exponent="1" offset="0"/>
      </feComponentTransfer>
    </filter>
  </defs>
    <rect x="100" y="420" width="600" height="60" fill="url(#MyGradient)" />
    <rect x="100" y="490" width="600" height="60" fill="url(#MyGradient)" filter="url(#Gamma)" />
</svg>

<svg width="300" height="500">
  <defs>
    <filter id="Gamma" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
      <feComponentTransfer>
      <feFuncR type="gamma" amplitude="2" exponent="5" offset="0"/>
      <feFuncG type="gamma" amplitude="2" exponent="3" 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="圖片網址" />
  <image x="0" y="200" width="300" height="200" xlink:href="圖片網址" filter="url(#Gamma)"  />
</svg>

了解了 feComponentTransfer 的基本原理之後,其實就已經可以簡單地針對圖片做顏色上的調整囉!雖然我還是覺得直接用影像處理軟體調整比較實在,不過若要製作一個線上調整圖片顏色的工具,也不失為一個好方式。


上一篇
Day26 - SVG filter - feGaussianBlur
下一篇
Day28 - SVG filter - feImage
系列文
SVG 30 天 ~ 就要醬玩31

尚未有邦友留言

立即登入留言