【第4章 图像与视频】4.6 结合剪辑区域来绘制图像

文章目录


前言

本节将综合运用图像处理、离屏 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-18-综合运用图像处理、离屏canvas以及剪辑区域等技术的墨镜效果演示</title>
		<style>
			#canvas {
				background: rgba(0, 0, 0, 0.4);
			}
		</style>
	</head>
	<body>
		<div id="controls">墨镜滤镜<input type="checkbox" id="sunglassCheckbox" /></div>
		<canvas id="canvas" width="800" height="600"> canvas not supports </canvas>

		<script>
			const canvas = document.getElementById('canvas'),
				context = canvas.getContext('2d'),
				sunglassCheckbox = document.getElementById('sunglassCheckbox'),
				offscreenCanvas = document.createElement('canvas'),
				offscreenContext = offscreenCanvas.getContext('2d'),
				sunglassFilter = new Worker('./sunglassFilter.js'),
				LENS_RADIUS = canvas.width / 5

			const image = new Image()

			offscreenCanvas.width = canvas.width
			offscreenCanvas.height = canvas.height

			// Functions......
			function drawOriginalImage() {
				context.drawImage(image, 0, 0, canvas.width, canvas.height)
			}

			// 绘制镜片
			function drawLenses(leftLensLocation, rightLensLocation) {
				context.save()

				context.beginPath()
				context.arc(leftLensLocation.x, leftLensLocation.y, LENS_RADIUS, 0, Math.PI * 2, false)
				context.stroke()

				moveTo(rightLensLocation.x, rightLensLocation.y)
				context.arc(rightLensLocation.x, rightLensLocation.y, LENS_RADIUS, 0, Math.PI * 2, false)
				context.stroke()

				context.clip()
				context.drawImage(offscreenCanvas, 0, 0, canvas.width, canvas.height)

				context.restore()
			}

			// 绘制镜线
			function drawWire(center) {
				context.beginPath()
				context.moveTo(center.x - LENS_RADIUS / 4, center.y - LENS_RADIUS / 2)
				context.quadraticCurveTo(
					center.x,
					center.y - LENS_RADIUS + 20,
					center.x + LENS_RADIUS / 4,
					center.y - LENS_RADIUS / 2
				)
				context.stroke()
			}

			function putSunglassesOn() {
				const imagedata = context.getImageData(0, 0, canvas.width, canvas.height),
					center = {
						x: canvas.width / 2,
						y: canvas.height / 2,
					},
					leftLensLocation = {
						x: center.x - LENS_RADIUS - 10,
						y: center.y,
					},
					rightLensLocation = {
						x: center.x + LENS_RADIUS + 10,
						y: center.y,
					}

				sunglassFilter.postMessage(imagedata)

				sunglassFilter.onmessage = (e) => {
					offscreenContext.putImageData(e.data, 0, 0)
					drawLenses(leftLensLocation, rightLensLocation)
					drawWire(center)
				}
			}

			// Event handlers......
			sunglassCheckbox.onchange = () => {
				if (sunglassCheckbox.checked) {
					putSunglassesOn()
				} else {
					drawOriginalImage()
				}
			}

			// Initialization......
			image.src = './waterfall.png'
			image.onload = () => {
				drawOriginalImage()
			}
		</script>
	</body>
</html>

Worker线程代码:

javascript 复制代码
self.onmessage = function (e) {
	const imagedata = e.data,
		data = imagedata.data,
		width = imagedata.width,
		length = data.length

	for (let i = 0; i < length; ++i) {
		if ((i + 1) % 4 != 0) {
			if ((i + 4) % (width * 4) == 0) {
				data[i] = data[i - 4]
				data[i + 1] = data[i - 3]
				data[i + 2] = data[i - 2]
				data[i + 3] = data[i - 1]
			} else {
				data[i] = 2 * data[i] - data[i + 4] - 0.5 * data[i + 4]
			}
		}
	}

	self.postMessage(imagedata)
}

相关推荐
风中凌乱的L2 天前
vue canvas标注
前端·vue.js·canvas
BetterChinglish2 天前
html5中canvas图形变换transform、setTransform原理(变换矩阵)
javascript·html5·canvas·变换矩阵
吃饺子不吃馅5 天前
Web端PPT应用画布方案:Canvas 还是 DOM?
前端·架构·canvas
吃饺子不吃馅7 天前
Canvas 如何渲染富文本、图片、SVG 及其 Path 路径?
前端·svg·canvas
纳兹咩programmer8 天前
uni-app踩坑记录-Canvas层级过高遮挡问题
canvas
吃饺子不吃馅10 天前
如何设计一个 Canvas 事件系统?
前端·canvas·图形学
吃饺子不吃馅12 天前
Canvas高性能Table架构深度解析
前端·javascript·canvas
吃饺子不吃馅12 天前
Canvas实现协同电影选座
前端·架构·canvas
水星梦月14 天前
跨平台开发中的图形渲染:Canvas与View+CSS的性能分析与决策路径
前端·css·图形渲染·canvas
华仔啊18 天前
用 Vue3 + Canvas 做了个超实用的水印工具,同事都在抢着用
前端·vue.js·canvas