【第4章 图像与视频】4.5 操作图像的像素

文章目录


前言

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-filterCanvas API中文网

相关推荐
ncj3934379061 天前
【第4章 图像与视频】4.6 结合剪辑区域来绘制图像
canvas
ncj3934379063 天前
【第1章 基础知识】1.8 在 Canvas 中使用 HTML 元素
canvas
七月shi人8 天前
Canvas设计图片编辑器全讲解(一)Canvas基础(万字图文讲解)
前端·javascript·canvas
wuhen_n9 天前
Canvas进阶篇:鼠标交互动画
javascript·html5·canvas·canvas动画·canvas拖拽
追求者201610 天前
实现图片自动压缩算法,canvas压缩图片方法
前端·javascript·canvas
prog_610323 天前
【笔记】当个自由的书籍收集者从canvas得到png转pdf
pdf·canvas·js·png
wuhen_n1 个月前
Canvas特效实例:黑客帝国-字母矩阵(字母雨)
前端·javascript·矩阵·html5·canvas·canva可画
_lucas1 个月前
用canvas做个场景编辑器
前端·javascript·canvas