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

news2025/6/2 7:43:10

文章目录

  • 前言
  • 示例-获取和修改图像数据
  • 图像数据的遍历方式
  • 图像滤镜
    • 负片滤镜
    • 黑白滤镜
    • 浮雕滤镜
    • filter滤镜属性


前言

getImageData() 与 putImageData() 这两个方法分别用来获取图像的像素信息,以及向图像中插入像素。与此同时,如果有需要,也可以修改像素的值,所以说,这两个方法能够让开发展对图像之中的像素进行任何可以想见的操作。

属性描述
width返回 ImageData 对象的宽度
height返回 ImageData 对象的高度
data返回一个对象,其包含指定的 ImageData 对象的图像数据
方法描述
createImageData()创建新的、空白的 ImageData 对象
getImageData()返回 ImageData 对象,该对象为画布上指定的矩形复制像素数据
putImageData()把图像数据(从指定的 ImageData 对象)放回画布上

示例-获取和修改图像数据

使用getImageData()方法获取imagedata数据源,然后仅中心100*100区域替换原始Canvas。

在这里插入图片描述

<!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>

图像数据的遍历方式

// 遍历每个像素
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 之中减去每个像素的红、绿、蓝分量值,再将差值设置回去,这样也就等于“反转”了该像素的颜色。

在这里插入图片描述

<!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>

黑白滤镜

黑白滤镜会计算出每个像素红、绿、蓝分量值的平均值,然后将三个分量都设置为这一均值,于是,就把图像由彩色变成了黑白。

在这里插入图片描述

<!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>

浮雕滤镜

在这里插入图片描述

<!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中文网

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2393346.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Science Advances 上海理工大学与美国杜克大学(Duke University)共同开发了一种仿生复眼相机

编辑丨%科学家开发了一种 AI 辅助的仿生复眼相机。炎炎夏日&#xff0c;相信各位读者都有被蚊子骚扰过的恼火记忆。但往往想要清剿蚊子的时候&#xff0c;却被它灵巧地躲开&#xff0c;再难找到。诸如蚊子这种节肢动物的视觉系统已经进化了 5 亿多年&#xff0c;从寒武纪一直到…

正点原子Z20 ZYNQ ​​​开发板​​发布!板载FMC LPC、LVDS LCD和WIFI蓝牙等接口,资料丰富!

正点原子Z20 ZYNQ ​​​开发板​​发布&#xff01;板载FMC LPC、LVDS LCD和WIFI&蓝牙等接口&#xff0c;资料丰富&#xff01; 正点原子新品Z20 ZYNQ开发板来啦&#xff01;核心板全工业级设计&#xff0c;主控芯片型号是XC7Z020CLG484-2I。开发板由核心板底板组成&…

软件测评中心如何确保软件品质?需求分析与测试计划很关键

软件测评中心承担着对软件进行评估、测试和审查的任务&#xff0c;它有一套规范的流程来确保软件的品质&#xff0c;并且能够向客户和开发者提供详实的软件状况分析报告。 需求分析环节 这一环节至关重要&#xff0c;必须与客户和开发团队保持密切交流。我们需要从他们那里精…

2025LitCTF 复现

easy_file 登录界面 尝试admin 和密码1 没成功 结果尝试了弱口令 admin 用户和 password 密码就登录成功了 文件上传 新建一个空的 新建木马.txt 文件发现上传成功 然后写入一句话木马 <?php eval($_POST[a]); ?> 上传失败 说明可能是有字符被过滤了&#xff0c;猜…

使用C# 快速删除Excel表格中的重复行数据-详解

目录 简介 使用工具 C# 删除Excel工作表中的重复行 C# 删除指定Excel单元格区域中的重复行 C# 基于特定列删除重复行 RemoveDuplicates 方法快速比较 简介 重复行是指在Excel表格中完全相同的多行数据。这些冗余行的存在可能源于多种原因&#xff0c;例如&#xff1a; …

WPF-Prism学习笔记之 “导航功能和依赖注入“

新建空白模板(Prism) 新建好后会有自动创建ViewModels和Views 在"MainWindow.xaml"文件里面标题去绑定了一个属性"Title"&#xff0c;而"MainWindowViewModel.cs"里面继承一个非常重要的"BindbleBase"(prism框架里面非常重要的)。所以…

中国城市间地理距离矩阵(2024)

1825 中国城市间地理距离矩阵(2024) 数据简介 中国城市间地理距离矩阵数据集&#xff0c;通过审图号GS(2024)0650的中国城市地图在Albers投影坐标系中进行计算得出矩阵表格&#xff0c;单位为KM&#xff0c;方便大家研究使用。 中国城市地理距离矩阵数据通过计算城市中心距离…

【备战秋招】C++音视频开发经典面试题整理

1、简要介绍一下对 H.264 的了解&#xff1f; 1&#xff09;基础描述 H.264 是由国际标准组织机构&#xff08;ISO&#xff09;下属的运动图象专家组&#xff08;MPEG&#xff09;和国际电传视讯联盟远程通信标准化组织&#xff08;ITU-T&#xff09;开发的系列编码标准之一。…

《java创世手记》---java基础篇(下)

《Java 创世手记 - 基础篇&#xff08;下&#xff09;》 第五章&#xff1a;契约与规范 —— 接口 (Interfaces) 与抽象类 (Abstract Classes) 造物主&#xff0c;在你日益繁荣的世界里&#xff0c;你发现仅仅依靠“继承”来构建“物种体系”有时会遇到一些限制。比如&#x…

【MySQL】C语言连接

要使用C语言连接mysql&#xff0c;需要使用mysql官网提供的库&#xff0c;大家可以去官网下载 我们使用C接口库来进行连接 要正确使用&#xff0c;我们需要做一些准备工作: 保证mysql服务有效在官网上下载合适自己平台的mysql connect库&#xff0c;以备后用 下载开发库 s…

新能源汽车与油车销量

中国油车与新能源车销量对比&#xff08;2022-2025年&#xff09; ‌1. 市场份额演化&#xff08;2022-2025年&#xff09;‌ ‌年份‌ ‌新能源车销量 &#xff08;渗透率&#xff09;‌ ‌燃油车销量 &#xff08;渗透率&#xff09;‌ ‌关键事件‌ ‌2022‌ 688.7万辆…

基于Java,SpringBoot,Vue,UniAPP宠物洗护医疗喂养预约服务商城小程序管理系统设计

摘要 随着宠物经济的快速发展&#xff0c;宠物主对宠物服务的便捷性、专业性需求日益增长。本研究设计并实现了一套宠物洗护医疗喂养预约服务小程序系统&#xff0c;采用 Java 与 SpringBoot 构建后端服务&#xff0c;结合 Vue 开发管理后台&#xff0c;通过 UniAPP 实现多端适…

中车靶场,网络安全暑期实训营

不善攻防&#xff0c;何谈就业&#xff1f; 实训目的&#xff1a;提升实战能力&#xff0c;直通就业快道。 实训对象&#xff1a;面向计算机相关专业、有兴趣接触网络攻防、大专及以上学历的学员。 知识准备 为确保高效实训&#xff0c;学员需具备一定的实战基础。报名后&am…

2.2.2 06年T1

成功的同化机器——美国&#xff1a;2006年考研英语&#xff08;一&#xff09;Text 1精析 本文解析2006年考研英语&#xff08;一&#xff09;第一篇文章&#xff0c;揭示美国社会强大的文化同化力及其表现。 一、原文与翻译 Paragraph 1&#xff1a;美国社会的同化本质 L1: …

【第1章 基础知识】1.8 在 Canvas 中使用 HTML 元素

文章目录 前言示例-橡皮筋式选取框示例代码 前言 尽管我们可以说 Canvas 是 HTML5 之中最棒的功能&#xff0c;不过在实现网络应用程序时&#xff0c;很少会单独使用它。在绝大多数情况下&#xff0c;你都会将一个或更多的 canvas 元素与其他 HTML 控件结合起来使用&#xff0…

c++流之sstream/堆or优先队列的应用[1]

目录 c流之sstream 解释 注意事项 215.数据流的第k大 问题分析 修正代码 主要修改点 优先队列的比较规则 代码中的比较逻辑 为什么这样能维护第 k 大元素&#xff1f; 举个例子 总结 Python 实现&#xff08;使用heapq库&#xff09; Java 实现&#xff08;使用P…

SAR ADC 比较器噪声分析(二)

SAR ADC的比较器是非常重要的模块&#xff0c;需要仔细设计。主要考虑比较器的以下指标&#xff1a; 1)失调电压 2)输入共模范围 3)比较器精度 4)传输延时 5)噪声 6)功耗 这里主要讲一下动态比较器的noise。 动态比较器一般用于高速SAR ADC中&#xff0c;且精度不会超过12bit…

机器学习Day5-模型诊断

实现机器学习算法的技巧。当我们训练模型或使用模型时&#xff0c;发现预测误差很 大&#xff0c;可以考虑进行以下优化&#xff1a; &#xff08;1&#xff09;获取更多的训练样本 &#xff08;2&#xff09;使用更少的特征 &#xff08;3&#xff09;获取其他特征 &#xff…

vscode一直连接不上虚拟机或者虚拟机容器怎么办?

1. 检查并修复文件权限 右键点击 C:\Users\20325\.ssh\config 文件&#xff0c;选择 属性 → 安全 选项卡。 确保只有你的用户账户有完全控制权限&#xff0c;移除其他用户&#xff08;如 Hena\Administrator&#xff09;的权限。 如果 .ssh 文件夹权限也有问题&#xff0c;同…

初学c语言21(文件操作)

一.为什么使用文件 之前我们写的程序的数据都是存储到内存里面的&#xff0c;当程序结束时&#xff0c;内存回收&#xff0c;数据丢失&#xff0c; 再次运行程序时&#xff0c;就看不到上次程序的数据&#xff0c;如果要程序的数据一直保存得使用文件 二.文件 文件一般可以…