javascript 实现图片亮度和对比度调整

1,104 阅读2分钟

这里采用基于 base64 解码的方式实现,有别与传统的借用 Image、Canvas 两个对象来处理,而是解码为二进制数据方式来进行处理,这个方式更为底层,有助于大家理解图形原理

核心:

window.atob// 解码

atob () 对经过 base-64 编码的字符串进行解码。你可以使用 window.btoa () 方法来编码一个可能在传输过程中出现问题的数据,并且在接受数据之后,使用 atob () 方法再将数据解码。例如:你可以编码、传输和解码操作各种字符,比如 0-31 的 ASCII 码值。

window.btoa// 二进制编码为字符串

btoa () 方法可以将一个二进制字符串(例如,将字符串中的每一个字节都视为一个二进制数据字节)编码为 Base64 编码的 ASCII 字符串。

ImageData

ImageData 接口描述 元素的一个隐含像素数据的区域。使用 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];
}