『不要再問我頭像如何變灰了,試試這幾種濾鏡吧!』

Canvas-Filter

在實際的工做中,有時候會有一些需求,讓你作一些圖片的濾鏡效果,好比將圖片變成黑白,調整圖片亮度等。本文手把手教你如何實現五種濾鏡效果,核心代碼總共不到 70 行。html

筆者所在的公司就有一個需求須要用到圖片處理的知識,大概場景我來描述一下:git

用戶能夠手動上傳印章,而且支持給印章設置不一樣的顯示效果,這裏的效果具體指的是「線條的清晰程度」,以下圖所示:github

這裏咱們使用 Canvas 來實現。若是你對 Canvas 不熟悉,建議看下以前我寫的一篇文章100 * 100 Canvas 佔用內存多大,花上幾分鐘看完,基本上夠看懂這篇文章了。web

準備工做

首先咱們先將圖片繪製到 Canvas 畫布上,爲了簡單起見,圖片大小固定爲 300 x 300。canvas

<canvas id="canvas" width="300px" height="300px"></canvas>
複製代碼

(html)數組

//獲取canvas元素
ctx = document.getElementById("canvas").getContext("2d");
//建立image對象
var img = new Image();
img.src = require("./seal.png");
//待圖片加載完後,將其顯示在canvas上
img.onload = () => {
  ctx.drawImage(img, 00);
  this.imgData = ctx.getImageData(00300300);
};
複製代碼

(js)dom

效果是這樣的:編輯器

操做像素

熟悉 Canvas 的應該知道上面的 this.imgData 實際上就是ImageData類的實例,其中 imgData.data 是一個 Uint8ClampedArray, 其描述了一個一維數組,包含以 RGBA 順序的數據,數據使用 0 至 255(包含)的整數表示。 簡單來講,就是圖片像素信息,每四位表示一個像素單元。其中每四位的信息分別是 RGBA。即第一個 Bit 標記 R,第二個 Bit 表示 G,第三個 Bit 表示 B,第四個 Bit 表示 A,第五個 Bit 又是 R...,依次類推。flex

接下來,咱們就要操做 imgData,來實現濾鏡的效果。簡單起見,我這裏對超過 200 的值進行了一次提升亮度的操做。實際上這個值是 200,仍是別的數字,須要咱們化身"調參工程師",不斷實驗才行。 而且粗暴地對 RGB 執行一樣的邏輯是不合理的。更爲合理的作法是對 RGB 的閥值分別進行度量,因爲比較麻煩,我這裏沒有實現。可是若是你對效果要求比較高,那麼最好能夠分開度量。ui

const data = this.imgData.data;
for (let i = 0; i < data.length; i += 4) {
  if (data[i] < 200) {
    data[i] = data[i] + brightness > 255 ? 255 : data[i] + brightness;
  }

  if (data[i + 1] < 200) {
    data[i + 1] =
      data[i + 1] + brightness > 255 ? 255 : data[i + 1] + brightness;
  }
  if (data[i + 2] < 200) {
    data[i + 2] =
      data[i + 2] + brightness > 255 ? 255 : data[i + 2] + brightness;
  }
}
複製代碼

如上,咱們對圖片的像素進行了處理,以達到咱們的目的,這樣從用戶感官上來看,顯示效果發生了變化,大概效果如圖:

(清晰版)

(模糊版)

若是你願意的話,你也能夠將處理好的圖片進行導出,也很簡單,直接調用 Canvas 實例的 toDataURL 方法便可,圖片保存的格式也能夠在這個方法中進行指定。

平常開發中,咱們還可能碰到不少其餘的濾鏡效果。下面介紹幾個比較現常見的效果。 若是你正好用到了不妨做爲參考。若是遇到了新的濾鏡效果, 不妨在文末向我留言,看到後會及時回答,提早感謝你的參與。

下面介紹其餘四種濾鏡效果。這裏只貼出核心代碼,完整代碼能夠訪問個人 Github Repo 進行查看。若是你嫌下載到本地麻煩,也能夠在這裏在線安裝並訪問,打開這個連接,分別執行yarnyarn start便可。

如下效果均如下圖爲原圖製做:

如何實現黑白效果

for (let i = 0; i < data.length; i += 4) {
  // 將紅黃藍按照必定比例混合,具體比例爲0.299 : 0.587 : 0.114, 這個比例須要慢慢調製。
  const avg = 0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2];
  data[i] = data[i + 1] = data[i + 2] = avg;
}
複製代碼

如何實現反色效果

for (let i = 0; i < data.length; i += 4) {
  data[i] = 255 - data[i]; //r
  data[i + 1] = 255 - data[i + 1]; //g
  data[i + 2] = 255 - data[i + 2]; //b
}
複製代碼

如何給圖片增長噪音

const random = ((Math.random() * 70) >>> 0) - 35;
for (let i = 0; i < data.length; i += 4) {
  data[i] = data[i] + random;
  data[i + 1] = data[i + 1] + random;
  data[i + 2] = data[i + 2] + random;
}
複製代碼

如何提升圖片亮度

const brightness = +e.target.value;
for (let i = 0; i < data.length; i += 4) {
  data[i] = data[i] + brightness > 255 ? 255 : data[i] + brightness;
  data[i + 1] = data[i + 1] + brightness > 255 ? 255 : data[i + 1] + brightness;
  data[i + 2] = data[i + 2] + brightness > 255 ? 255 : data[i + 2] + brightness;
}
複製代碼

總結

本文經過不到 70 行代碼實現了五種濾鏡效果,對於其餘濾鏡效果也能夠參考這種方式來實現。還不趕忙拿上小姐姐的照片來秀一手麼?

相關文章
相關標籤/搜索