瀏覽器端javascript調整圖片亮度和對比度

這裏採用基於base64解碼的方式實現,有別與傳統的借用Image、Canvas兩個對象來處理,而是解碼爲二進制數據方式來進行處理,這個方式更爲底層,有助於大家理解圖形原理

核心:

window.atob //解碼

atob() 對經過 base-64 編碼的字符串進行解碼。你可以使用 window.btoa() 方法來編碼一個可能在傳輸過程中出現問題的數據,並且在接受數據之後,使用 atob() 方法再將數據解碼。例如:你可以編碼、傳輸和解碼操作各種字符,比如 0-31 的 ASCII 碼值。

window.btoa //二進制編碼爲字符串

btoa() 方法可以將一個二進制字符串(例如,將字符串中的每一個字節都視爲一個二進制數據字節)編碼爲 Base64 編碼的 ASCII 字符串。

ImageData

ImageData 接口描述 <canvas> 元素的一個隱含像素數據的區域。使用 ImageData() 構造函數創建或者使用和 canvas 在一起的 CanvasRenderingContext2D 對象的創建方法: createImageData() 和 getImageData()。也可以使用 putImageData() 設置 canvas 的一部分。

代碼

const adjustImage = (base64Image, brightnessDelta, contrastGamma)=> {
new Promise((resolve, reject) => {
  // 將 base64 編碼的字符串解碼爲二進制數據
  const binary = atob(base64Image.split(',')[1]);

  // 計算圖片大小
  const imageSize = binary.length;

  // 計算圖片寬度和高度
  const sizeData = binary.substr(0, 16).match(/(\d+)x(\d+)/);
  const imageWidth = parseInt(sizeData[1]);
  const imageHeight = parseInt(sizeData[2]);

  // 創建一個新的 Uint8ClampedArray 對象,將像素數據寫入其中
  const pixels = new Uint8ClampedArray(imageSize - 16);
  for (let i = 16, j = 0; i < imageSize; i++, j++) {
    pixels[j] = binary.charCodeAt(i);
  }

  // 創建一個新的 ImageData 對象,使用解碼後的像素數據
  const imageData = new ImageData(pixels, imageWidth, imageHeight);
  const data = imageData.data;

  // 遍歷所有像素,修改亮度和對比度
  for (let i = 0; i < data.length; i += 4) {
    const r = data[i];
    const g = data[i + 1];
    const b = data[i + 2];

    // 降低亮度
    const [newR, newG, newB] = decreaseBrightness(r, g, b, brightnessDelta);

    // 降低對比度
    const [finalR, finalG, finalB] = decreaseContrast(newR, newG, newB, contrastGamma);

    // 將修改後的像素寫回 imageData
    data[i] = finalR;
    data[i + 1] = finalG;
    data[i + 2] = finalB;
  }

  // 將修改後的 imageData 轉換爲 base64 編碼的圖像
  const binaryImageData = String.fromCharCode.apply(null, imageData.data);
   resolve( 'data:image/png;base64,' + btoa(binaryImageData));
  }
}

// 降低亮度
const decreaseBrightness = (r, g, b, delta) =>{
  r = Math.max(0, r - delta);
  g = Math.max(0, g - delta);
  b = Math.max(0, b - delta);
  return [r, g, b];
}

// 降低對比度
const decreaseContrast = (r, g, b, gamma) =>{
  let luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
  let factor = (259 * (gamma + 255)) / (255 * (259 - gamma));
  let newR = Math.max(0, Math.min(factor * (r - luminance) + luminance, 255));
  let newG = Math.max(0, Math.min(factor * (g - luminance) + luminance, 255));
  let newB = Math.max(0, Math.min(factor * (b - luminance) + luminance, 255));
  return [newR,newG, newB];
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章