文章目录
前言
getImageData() 与 putImageData() 这两个方法分别用来获取图像的像素信息,以及向图像中插入像素。与此同时,如果有需要,也可以修改像素的值,所以说,这两个方法能够让开发展对图像之中的像素进行任何可以想见的操作。
属性 | 描述 |
---|---|
width | 返回 ImageData 对象的宽度 |
height | 返回 ImageData 对象的高度 |
data | 返回一个对象,其包含指定的 ImageData 对象的图像数据 |
方法 | 描述 |
---|---|
createImageData() | 创建新的、空白的 ImageData 对象 |
getImageData() | 返回 ImageData 对象,该对象为画布上指定的矩形复制像素数据 |
putImageData() | 把图像数据(从指定的 ImageData 对象)放回画布上 |
示例-获取和修改图像数据
使用getImageData()方法获取imagedata数据源,然后仅中心100*100区域替换原始Canvas。

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>4-9-putImageData使用示例</title>
<style>
html,
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas id="canvas" width="300" height="200"> canvas not supports </canvas>
<script>
// 尺寸
const width = 300,
height = 200
// 目标Canvas上下文
const canvas = document.getElementById('canvas'),
context = canvas.getContext('2d')
// 目标图片
const image1 = new Image()
image1.src = './3.jpg'
image1.onload = () => {
context.drawImage(image1, 0, 0, width, height)
}
// 覆盖图片
const image2 = new Image()
image2.src = './2.jpg'
image2.onload = function () {
// 获取覆盖图数据
const dirtyCanvas = document.createElement('canvas'),
dirtyContext = dirtyCanvas.getContext('2d')
// 设置屏幕外Canvas尺寸
dirtyCanvas.width = width
dirtyCanvas.height = height
// 绘制替换图
dirtyContext.drawImage(this, 0, 0, width, height)
// 此时可以得到imagedata数据
const imagedata = dirtyContext.getImageData(0, 0, width, height)
// console.log(imagedata)
// 然后中间100*100区域替换目标Canvas
context.putImageData(imagedata, 0, 0, 100, 50, 100, 100)
}
</script>
</body>
</html>
图像数据的遍历方式
javascript
// 遍历每个像素
for (let i = 0; i < length, ++i) {
value = data[i]
}
// 反向遍历每个像素
index = length - 1
while (index > = 0) {
value = data[index]
index--
}
// 只处理 alpha 值,不修改红、绿、蓝分量
for(let index=3; index < length - 4; index+=4) {
data[index] = ... // Alpha
}
// 只处理红、绿、蓝分量,不修改 alpha 值
for(let index=0; index < length - 4; index+=4) {
data[index] = ... // Red
data[index + 1] = ... // Green
data[index + 2] = ... // Blue
}
图像滤镜
原始图片:
负片滤镜
负片滤镜会从 255 之中减去每个像素的红、绿、蓝分量值,再将差值设置回去,这样也就等于"反转"了该像素的颜色。

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>4-13-负片滤镜</title>
<style>
#canvas {
background: rgba(0, 0, 0, 0.4);
}
</style>
</head>
<body>
<div id="controls">负片滤镜<input type="checkbox" id="negativeCheckbox" /></div>
<canvas id="canvas" width="1000" height="600"> canvas not supports </canvas>
<script>
const canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
negativeCheckbox = document.getElementById('negativeCheckbox')
const image = new Image()
image.src = './waterfall.png'
image.onload = () => {
context.drawImage(image, 0, 0, canvas.width, canvas.height)
}
negativeCheckbox.onchange = (e) => {
const imagedata = context.getImageData(0, 0, canvas.width, canvas.height),
data = imagedata.data
for (let i = 0; i < data.length - 4; i += 4) {
data[i] = 255 - data[i]
data[i + 1] = 255 - data[i + 1]
data[i + 2] = 255 - data[i + 2]
}
context.putImageData(imagedata, 0, 0)
}
</script>
</body>
</html>
黑白滤镜
黑白滤镜会计算出每个像素红、绿、蓝分量值的平均值,然后将三个分量都设置为这一均值,于是,就把图像由彩色变成了黑白。

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>4-14-黑白滤镜</title>
<style>
#canvas {
background: rgba(0, 0, 0, 0.4);
}
</style>
</head>
<body>
<div id="controls">黑白滤镜<input type="checkbox" id="drawInColorToggleChebox" /></div>
<canvas id="canvas" width="1000" height="600"> canvas not supports </canvas>
<script>
const canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
drawInColorToggleChebox = document.getElementById('drawInColorToggleChebox')
function drawInColor() {
context.drawImage(image, 0, 0, canvas.width, canvas.height)
}
function drawInBlackAndWhite() {
const imagedata = context.getImageData(0, 0, canvas.width, canvas.height),
data = imagedata.data
for (let i = 0; i < data.length - 4; i += 4) {
average = (data[i] + data[i + 1] + data[i + 2]) / 3
data[i] = average
data[i + 1] = average
data[i + 2] = average
}
context.putImageData(imagedata, 0, 0)
}
const image = new Image()
image.src = './waterfall.png'
image.onload = () => {
drawInColor()
}
drawInColorToggleChebox.onchange = (e) => {
if (e.target.checked) {
drawInBlackAndWhite()
} else {
drawInColor()
}
}
</script>
</body>
</html>
浮雕滤镜

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>4-14-浮雕滤镜</title>
<style>
#canvas {
background: rgba(0, 0, 0, 0.4);
}
</style>
</head>
<body>
<div id="controls">浮雕滤镜<input type="checkbox" id="embossCheckbox" /></div>
<canvas id="canvas" width="1000" height="600"> canvas not supports </canvas>
<script>
const canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
embossCheckbox = document.getElementById('embossCheckbox')
function drawOriginalImage() {
context.drawImage(image, 0, 0, canvas.width, canvas.height)
}
function drawEmbossImage() {
let iamgedata, data, length, width
iamgedata = context.getImageData(0, 0, canvas.width, canvas.height)
data = iamgedata.data
length = data.length
width = iamgedata.width
index = 3
for (let i = 0; i < length; i++) {
if ((i + 1) % 4 !== 0) {
data[i] = 255 / 2 + 2 * data[i] - data[i + 4] - data[i + width * 4]
}
}
context.putImageData(iamgedata, 0, 0)
}
const image = new Image()
image.src = './waterfall.png'
image.onload = () => {
drawOriginalImage()
}
embossCheckbox.onchange = (e) => {
if (e.target.checked) {
drawEmbossImage()
} else {
drawOriginalImage()
}
}
</script>
</body>
</html>
filter滤镜属性
Canvas 2D API 的 CanvasRenderingContext2D.filter 属性是用来提供模糊、灰度等滤镜效果。它类似于 CSS filter 属性,并且接受相同的值。
具体说明见 MDN-filter 或 Canvas API中文网

