【第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中文网

相关推荐
用户2519162427115 小时前
Canvas之图形变换
前端·javascript·canvas
FogLetter6 小时前
用Three.js打造炫酷3D地球:从入门到实现交互式体验
webgl·canvas
寅时码12 小时前
我开源了一款 Canvas “瑞士军刀”,十几种“特效与工具”开箱即用
前端·开源·canvas
德育处主任1 天前
p5.js 用 beginGeometry () 和 endGeometry () 打造自定义 3D 模型
前端·前端框架·canvas
德育处主任3 天前
p5.js 3D模型(model)入门指南
前端·前端框架·canvas
VincentFHR4 天前
Three.js 利用 shader 实现 3D 热力图
前端·three.js·canvas
德育处主任5 天前
p5.js 加载 3D 模型(loadModel)
前端·数据可视化·canvas
用户2519162427116 天前
Canvas之颜色渐变
前端·javascript·canvas
德育处主任6 天前
p5.js 从零开始创建 3D 模型,createModel入门指南
前端·数据可视化·canvas
德育处主任6 天前
p5.js 三角形triangle的用法
前端·数据可视化·canvas