Skip to main content

Canvas 图片处理

1. 图片压缩

以下是一个使用 Canvas 实现的图片压缩示例:

实现原理

  1. 使用 Canvas 调整图片尺寸
  2. 通过 quality 参数控制压缩质量
  3. 转换为 Blob 对象输出
const compressImage = (file: File): Promise<Blob> => {
return new Promise((resolve) => {
const img = new Image();
img.src = URL.createObjectURL(file);

img.onload = () => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d')!;

// 计算缩放比例
let width = img.width;
let height = img.height;

if (width > maxWidth) {
height = (maxWidth * height) / width;
width = maxWidth;
}

// 设置 canvas 尺寸
canvas.width = width;
canvas.height = height;

// 绘制图片
ctx.drawImage(img, 0, 0, width, height);

// 转换为 blob
canvas.toBlob(
(blob) => resolve(blob!),
'image/jpeg',
quality
);
};
});
};

2. 其他图片处理功能

滤镜效果

// 灰度滤镜
ctx.filter = 'grayscale(100%)';
ctx.drawImage(img, 0, 0);

// 模糊滤镜
ctx.filter = 'blur(5px)';
ctx.drawImage(img, 0, 0);

// 亮度调整
ctx.filter = 'brightness(150%)';
ctx.drawImage(img, 0, 0);

像素操作

// 获取像素数据
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;

// 修改像素
for (let i = 0; i < data.length; i += 4) {
// 反转颜色
data[i] = 255 - data[i]; // red
data[i + 1] = 255 - data[i + 1]; // green
data[i + 2] = 255 - data[i + 2]; // blue
// data[i + 3] 是 alpha 通道
}

// 将修改后的像素数据放回 canvas
ctx.putImageData(imageData, 0, 0);

图片裁剪

const cropImage = (x: number, y: number, width: number, height: number) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d')!;

canvas.width = width;
canvas.height = height;

// 绘制裁剪区域
ctx.drawImage(
sourceCanvas,
x, y, width, height, // 源图像裁剪区域
0, 0, width, height // 目标区域
);

return canvas;
};

3. 性能优化

1. 缓存 Canvas

// 创建离屏 canvas
const offscreenCanvas = document.createElement('canvas');
const offscreenCtx = offscreenCanvas.getContext('2d');

// 在离屏 canvas 中处理图片
offscreenCtx.drawImage(img, 0, 0);

// 最后一次性绘制到显示 canvas
displayCtx.drawImage(offscreenCanvas, 0, 0);

2. 使用 requestAnimationFrame

const animate = () => {
// 处理图片
processImage();

// 下一帧继续
requestAnimationFrame(animate);
};

requestAnimationFrame(animate);

3. 使用 Web Workers

// 创建 Worker
const worker = new Worker('imageProcessor.js');

// 发送数据给 Worker
worker.postMessage({
imageData: ctx.getImageData(0, 0, width, height),
params: { brightness: 1.2, contrast: 1.1 }
});

// 接收处理结果
worker.onmessage = (e) => {
ctx.putImageData(e.data, 0, 0);
};