CSS filter與前端濾鏡

今天(2020.04.04)不少網站都換成了灰色調,如淘寶百度掘金知乎等,經過實地考察,灰度的技術無一例外都使用瞭如下CSS,如淘寶的:html

html {
    -webkit-filter: grayscale(100%);
    filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}複製代碼

第一行對非IE瀏覽器生效,第二行是對IE瀏覽器生效(emmm...彷佛瀏覽器就分爲兩種),本質上都是使用filter的grayscale屬性,實現灰階效果,灰階是一種經常使用的圖片濾鏡。打開PS能夠看到多種濾鏡可選擇:git

而經過CSS的filter可以實現其中的一些濾鏡效果,如灰階,高斯模糊等。github

這個時候你可能會問,網頁又不是圖片,裏面可能會有不少文本,爲何也能應用圖片的濾鏡呢?實際上網頁在渲染到屏幕以前都會被柵格化成Canvas位圖再畫到屏幕上,因此filter處理的就是這張位圖。web

經過Chromime源碼,咱們能夠看到相關濾鏡的實現,其實是使用了一個圖像矩陣對原始位圖進行轉換,以下代碼所示:算法

void GetGrayscaleMatrix(float amount, float matrix[20]) {
  // Note, these values are computed to ensure MatrixNeedsClamping is false
  // for amount in [0..1]
  matrix[0] = 0.2126f + 0.7874f * amount;
  matrix[1] = 0.7152f - 0.7152f * amount;
  matrix[2] = 1.f - (matrix[0] + matrix[1]);
  matrix[3] = matrix[4] = 0.f;

  matrix[5] = 0.2126f - 0.2126f * amount;
  matrix[6] = 0.7152f + 0.2848f * amount;
  matrix[7] = 1.f - (matrix[5] + matrix[6]);
  matrix[8] = matrix[9] = 0.f;

  matrix[10] = 0.2126f - 0.2126f * amount;
  matrix[11] = 0.7152f - 0.7152f * amount;
  matrix[12] = 1.f - (matrix[10] + matrix[11]);
  matrix[13] = matrix[14] = 0.f;

  matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
  matrix[18] = 1.f;
}複製代碼

這個便爲灰階grayscale的矩陣獲取方式,若是CSS傳的amount值爲1(上面參數的便爲1 - amount = 0,代碼傳參的時候使用了和1的差值),那麼將獲得如下矩陣:windows

這個矩陣即是用來對每一個像素點進行轉換,假設某個像素點的像素值爲rgba(255, 119, 50, 0.5),那麼這個像素點轉換計算以下:瀏覽器

實際上對RGB每一位的計算爲:bash

R/G/B = 255 * 0.2126 + 119 * 0.7152 + 50 * 0.0722 = 143網站

即便用公式:ui

Y'=0.2126R'+0.7152G'+0.0722B'

這個其實就是灰階算法,所謂灰階例如黑白電視即是像素點只用一個維度表示:淺或深,因此須要把RGB三維數據處理成一維的,最簡單的即是取RGB的平均值便可,但更科學的應該是用人眼對三原色的感知程度分配係數,這樣能提升對比度。

那麼爲何上面須要用一個矩陣計算呢,實際上統一成一個矩陣有一個顯而易見好處是作多重變換的時候,只須要對這個矩陣進行累乘獲得一個最終的矩陣便可,相似於transform. 例如能夠在灰階以後再加上棕褐色(sepia)的處理:

html {
  filter: grayscale(1) sepia(0.5);
}複製代碼

以下圖對比:

棕褐色的矩陣獲取方式爲:

若是灰階的矩陣爲A,棕褐色矩陣爲B,那麼這次的變換矩陣便爲A * B(注意矩陣通常不知足交換律,A * B不等於B *A),若是咱們先作棕褐色處理再作灰階的話,最後的效果就是灰階的。

咱們發現Direct2D等引擎也是使用的這種方式進行變換,只不過採用的矩陣會有點差別:

其它相對簡單的濾鏡如色調旋轉(hue-rotate),反相(invert)等都是採用的這種矩陣變換,可是對於高斯模糊(blur)、投影(drop-shadow)等則是須要一些更復雜的算法,在源碼裏能夠看到,高斯模糊是使用Skia的SkBlurImageFilter類作的處理,具體的計算過程可見源碼。無論是矩陣仍是單獨的處理,它們都是繼承於PaintFilter.

最後,本篇主要簡單介紹了下filter濾鏡的一些原理,經過採用一個圖像變換矩陣作的處理,不一樣的濾鏡變換的公式不同,所採用的矩陣也不同,多種效果能夠經過矩陣累積成一個新的矩陣。同時,對於模糊和投影單獨有一些更加高級的處理。

相關文章
相關標籤/搜索