HTML5 Video & Canvas 协同使用
本作品采用 CC BY-NC-SA 4.0 授权,本作品包含 CC BY 3.0 的内容(视频),该部分仍适用原始许可,不受本作品的 CC BY-NC-SA 4.0 限制。视频为 Big Buck Bunny。
建议阅读前先学习 Canvas 相关知识。
相关 API
本文使用的相关新 API 如下:
CanvasRenderingContext2D.drawImage
:还记得吗?上一期我们用它画出了一个洛谷的 logo。这次,它的参数将变为一个<video>
。ImageData CanvasRenderingContext2D.getImageData(double x,double y,double sw, double sh);
:这里的sw
与sh
代表宽和高。struct ImageData { // 这是 ImageData 的 C++ 表示。 /*readonly*/ unsigned long width; // 对应 sw。 /*readonly*/ unsigned long height; // 对应 sh。 /*readonly*/ uint8_t[] data; // 我们要操作的数组。只读并非是不能改,可以 data[x] = y 这样改,不能 data=some。 };
- CanvasRenderingContext2D.putImageData(ImageData data, double x, double y) 写回
ImageData
到canvas
中。
data
数组中,对于第
Step 1:准备工作
准备一个标准的 HTML 页面和一个视频。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>HTML Canvas API</title>
<style>
/*
这里会有样式……
*/
#buffer{
display: none;
}
</style>
</head>
<body>
<div id="content">
<canvas id="cvs" width="1920" height="1080"></canvas>
<canvas id="buffer" width="1920" height="1080"></canvas>
<video id="video" src="video.mp4" width="1920" height="1080" autoplay></video>
</div>
<script>
// 编程区
const vid = document.getElementById("video");
const buf = document.getElementById("buffer");
const output = document.getElementById("cvs")
let func = time => {
};
func();
</script>
</body>
</html>
Step 2: 效果实现
我们可以先把视频的每一帧放到一个缓冲区里(buffer
,不显示)提取,再进行处理,把处理完的帧写回到输出显示(cvs
)中。
在 func
内添加如下代码:
bufctx.drawImage(vid,0,0); // 读取帧
let data = data.getImageData(0,0,1920,1080); // 帧数据
let len = bufctx.data.length / 4; // 像素数据
for(let i=0;i<len;i++){ // 对于每一个像素……
let r=data.data[4*i]; // R 值
let g=data.data[4*i+1]; // G 值
let b=data.data[4*i+2]; // B 值
data[4*i]=data[4*i+1]=data[4*i+2]=(r+g+b)/3; // 灰度效果
}
outctx.putImageData(data,0,0); // 输出
这段代码把每个像素的 RGB 取平均,就得到了灰度的效果。效果如下:
Step 3: 更多效果
还可以做出黑白双色效果,将 data[4*i+1]=data[4*i+1]=data[4*i+2]=(r+g+b)/3
改为 data.data[4*i+1]=data.data[4*i+1]=data.data[4*i+2]=(r+g+b)/3>128 ? 255 : 0;
。效果如下:
你还可以做出反色效果,试一试吧!效果应该是这样的:
Ref.
- MDN
- W3C Canvas 规范