iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 10
2
Modern Web

用 Javascript 當個影像魔術師系列 第 10

Day 10 - 圖片效果 - 飽和度

Day 10 圖片效果 - 飽和度

飽和度

昨天已經介紹到已經將顏色轉成 HSV 的形式,那今天就可以來介紹飽和度調整的部分囉,飽和度也是調整照片中常用的選項,透過飽和度的調整可以讓整個相片帶給人不同的視覺感官,通常來說在自然、風景類的照片中會呈現比較鮮艷的顏色。

實作

來看一下算法的部分吧,因為昨天已經轉換成 HSV 的呈現方式了,今天要做的只是將 S 加上強度,但最後要記得轉換回去 RGB 的呈現方式

export const saturation = (pixelData, amount) => {
  for (let i = 0; i < pixelData.length; i += 4) {
    const [r, g, b] = [pixelData[i], pixelData[i + 1], pixelData[i + 2]]
    const hsv = rgbToHsv(r, g, b)
    hsv[1] = clamp(hsv[1] + amount, 0, 100)
    const finalRgb = hsvToRgb(hsv)
    pixelData[i] = finalRgb[0]
    pixelData[i + 1] = finalRgb[1]
    pixelData[i + 2] = finalRgb[2]
  }
  return pixelData
}

因為 S 的最大值為 100,但是我們加上去的值卻有可能會超過,所以實作了一個通用函數,之後應該也會常用到,主要用途就是給定一個值,超過上下限的值就會轉變成最近的界線

export const clamp = (input, min, max) => {
  return Math.min(Math.max(input, min), max)
}

其實之前其他的算法就有機會超過 255 的值了,但是因為我們是直接對 RGB 做操作,所以之後在放回去 Unit8ClampArray 的時候會自動幫我們把超出邊界的值歸位,所以如果是用其他語言實作的話請注意這個問題。

因為這次還會需要轉回去 RGB 所以要特別注意一下。

接下來就是 HSV to RGB 的轉換了,這裡 有轉換數學公式,一樣參考同一個 Repo 實現

export const hsvToRgb = hsv => {
  const h = hsv[0] / 60
  const s = hsv[1] / 100
  let v = hsv[2] / 100
  const hi = Math.floor(h) % 6

  const f = h - Math.floor(h)
  const p = 255 * v * (1 - s)
  const q = 255 * v * (1 - s * f)
  const t = 255 * v * (1 - s * (1 - f))
  v *= 255

  switch (hi) {
    case 0:
      return [v, t, p]
    case 1:
      return [q, v, p]
    case 2:
      return [p, v, t]
    case 3:
      return [p, q, v]
    case 4:
      return [t, p, v]
    case 5:
      return [v, p, q]
  }
}

一樣在 State 增加值及增加 Slider 元件,流程跟前幾篇一樣,就不特別多說了。

小結

照片拍攝在班公錯湖,也就是三個傻瓜裡面結尾最後的地方,很美!

來看看這次的效果吧,拖到最底的時候發現天空的顏色好像不太對( 原本白色的部分轉藍了,注意圖片左上角 ),明天來看一下要怎麼調整吧


上一篇
Day 09 - 圖片色彩模型
下一篇
Day 11 - 圖片效果 - 細節飽和度
系列文
用 Javascript 當個影像魔術師30

尚未有邦友留言

立即登入留言