【图形学】颜色线性插值和Wu反走样算法

颜色线性插值

绘制一条颜色渐变的直线,直线上每一个点的颜色都来自端点颜色的线性插值。线性插值公式为
P = ( 1 − t ) P s t a r t + t P e n d P 是直线上任意一个点, P s t a r t 是直线的起点, P e n d 是直线的终点 对应直线上任意一点的颜色有 c = ( 1 − t ) c s t a r t + t c e n d P=(1-t)P_{start}+tP_{end}\\ P是直线上任意一个点,P_{start}是直线的起点,P_{end}是直线的终点\\对应直线上任意一点的颜色有\\c=(1-t)c_{start}+tc_{end} P=(1t)Pstart+tPendP是直线上任意一个点,Pstart是直线的起点,Pend是直线的终点对应直线上任意一点的颜色有c=(1t)cstart+tcend
根据之前学的直线光栅化算法可知,绘制直线的时候是有主位移方向的,如果主位移方向是x,有 x = ( 1 − t ) x s t a r t + t x e n d x=(1-t)x_{start}+tx_{end} x=(1t)xstart+txend如果主位移方向是y有 y = ( 1 − t ) y s t a r t + t y e n d y=(1-t)y_{start}+ty_{end} y=(1t)ystart+tyend。带入到上面的公式有 c = x e n d − x x e n d − x s t a r t ⋅ c s t a r t + x − x s t a r t x e n d − x s t a r t ⋅ c e n d 或者 c = y e n d − y y e n d − y s t a r t ⋅ c s t a r t + y − y s t a r t y e n d − y s t a r t ⋅ c e n d c=\frac{x_{end}-x}{x_{end}-x_{start}}\cdot c_{start}+\frac{x-x_{start}}{x_{end}-x_{start}}\cdot c_{end}或者c=\frac{y_{end}-y}{y_{end}-y_{start}}\cdot c_{start}+\frac{y-y_{start}}{y_{end}-y_{start}}\cdot c_{end} c=xendxstartxendxcstart+xendxstartxxstartcend或者c=yendystartyendycstart+yendystartyystartcend
综合来看就是下面的代码
在这里插入图片描述

CRGB CLine::LinearInterP(double t, double tStart, double tEnd, CRGB cStart, CRGB cEnd)
{
    CRGB color;
    color = (tEnd - t) * cStart / (tEnd - tStart) + (t - tStart) * cEnd / (tEnd - tStart);
    return color;
}

在画直线的时候调用这个算法就可以画出颜色渐变的直线,这里以Bresenham算法为例。

#define COLOR(x) RGB(x.m_red*255,x.m_green*255,x.m_blue*255)

在这里插入图片描述

void CLine::DrawLine(CDC* pDC)
{
	int dx = abs(m_p1.x - m_p0.x);//m_p0,m_p1(CPoint2)
	int dy = abs(m_p1.y - m_p0.y);
	double k = (double)(dy) / (double)(dx);  //斜率
	BOOL wayChange = FALSE;//主方向是否发生改变,默认是x方向
	int e, mainway, subway;
	e = -dx;
	mainway = dx;
	subway = dy;
	int addx, addy;
	addx = (m_p1.x > m_p0.x) ? 1 : ((m_p1.x < m_p0.x) ? -1 : 0);
	addy = (m_p1.y > m_p0.y) ? 1 : ((m_p1.y < m_p0.y) ? -1 : 0);
	if (dy > dx) {//主方向是y
		mainway = dy;
		subway = dx;
		wayChange = TRUE;
	}
	CPoint2 p = m_p0;
	for (int i = 0; i <= mainway; i++) {
		pDC->SetPixel(p.x,p.y, COLOR(p.c));
		if (wayChange) {
			p.c = LinearInterP(p.y,m_p0.y,m_p1.y,m_p0.c,m_p1.c);
			p.y += addy;
		}	
		else {
			p.c = LinearInterP(p.x, m_p0.x, m_p1.x, m_p0.c, m_p1.c);
			p.x += addx;
		}	
		e += 2 * subway;
		if (e >= 0) {
			if (wayChange)
				p.x += addx;
			else
				p.y += addy;
			e -= 2 * mainway;
		}
	}
}

在这里插入图片描述

Wu反走样算法

在这里插入图片描述

直线扫描转换算法在处理非水平,非垂直和非45度直线会出现如图所示的锯齿或台阶转边界,这样的现象称为走样,走样只能减轻但不能避免。

Wu反走样算法是以Bresenham算法为基础对距离进行加权的一种算法。
在这里插入图片描述
如果采用Bresenham算法,那么显示的是点D,对于Wu反走样算法,理想直线上的点C的上下两个可能近似点都要显示,但是亮度不同。一个像素点距离理想直线距离越远,该像素点的颜色就越接近背景色,亮度就越大;一个像素点距离理想直线越近该像素点的颜色就越接近理想直线,亮度就越小。
例如点C和点D的距离为e,那么点D的亮度就是e,点E的亮度就是1-e。
算法中e的递推式就是Bresenham算法中距离误差d的递推式。
主位移方向每递增一个单位有 e i + 1 = e i + k 当 e i + 1 ≥ 1.0 时 e i + 1 要减 1 e_{i+1}=e_i+k当e_{i+1}\geq1.0时e_{i+1}要减1 ei+1=ei+kei+11.0ei+1要减1

void CALine::DrawLine(CDC* pDC)
{
	int dx = abs(m_p1.x - m_p0.x);//m_p0,m_p1(CPoint)
	int dy = abs(m_p1.y - m_p0.y);
	double k = (double)(dy) / (double)(dx);  //斜率
	BOOL wayChange = FALSE;//主方向是否发生改变,默认是x方向
	int  mainway, subway;
	double e = 0.0;
	mainway = dx;
	subway = dy;
	int addx, addy;
	addx = (m_p1.x > m_p0.x) ? 1 : ((m_p1.x < m_p0.x) ? -1 : 0);
	addy = (m_p1.y > m_p0.y) ? 1 : ((m_p1.y < m_p0.y) ? -1 : 0);
	if (dy > dx) {//主方向是y
		mainway = dy;
		subway = dx;
		wayChange = TRUE;
	}
	CPoint2 p = m_p0;
	for (int i = 0; i <= mainway; i++) {
		CRGB c0(e, e, e);
		CRGB c1(1 - e, 1 - e, 1 - e);
		if (wayChange) {
			pDC->SetPixelV(p.x + addx, p.y, COLOR(c1));
			pDC->SetPixelV(p.x, p.y, COLOR(c0));
		}
		else {
			pDC->SetPixelV(p.x, p.y + addy, COLOR(c1));
			pDC->SetPixelV(p.x, p.y, COLOR(c0));
		}
		if (wayChange) {
			p.y += addy;
		}
		else {
			p.x += addx;
		}
		e += (double)dy / dx;
		if (e >= 0.0) {
			if (wayChange)
				p.x += addx;
			else
				p.y += addy;
			e -= 1.0;
		}
	}
}

彩色的那条线是Bresenham算法画的直线,黑色的那条线是Wu反走样算法画的直线,将图片稍微放大就可以看到区别(一个比较粗糙,一个比较光滑)。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

gin+gorm增删改查目录框架

从网上找资料,发现,很多都是直接的结构 路由&#xff0c;后端的controller层&#xff0c;还有model层&#xff0c;都是放在了同一个main.go文件中&#xff0c;如果写项目的话&#xff0c;还得自己去拆文件&#xff0c;拆代码&#xff0c;经过查询和自己总结&#xff0c;下面放…

计算机网络——数据链路层(1)

一、概述 在计算机网络中&#xff0c;数据链路层承担着点对点通信的任务&#xff0c;用于跨物理层在网段节点之间参数数据。它在网络分层中处于物理层之上&#xff0c;网路层之下。 在链路层的讨论中&#xff0c;我们将看到两种截然不同类型的链路层信道。第一种类型是广播信道…

数字身份所有权:Web3时代用户数据的掌控权

随着Web3时代的来临&#xff0c;数字身份的概念正焕发出崭新的光芒。在这个数字化的时代&#xff0c;用户的个人数据变得愈加珍贵&#xff0c;而Web3则为用户带来了数字身份所有权的概念&#xff0c;重新定义了用户与个人数据之间的关系。本文将深入探讨Web3时代用户数据的掌控…

【竞技宝】DOTA2:世一C遇到瓶颈? yatoro直言一号位上分太难了

北京时间2024年1月18日&#xff0c;spirit在去年再次拿到了TI国际邀请赛的冠军&#xff0c;成为了OG之后第二支两次在世界赛夺冠的战队&#xff0c;在夺冠之后&#xff0c;spirit直接给选手们放了假。此前AR夺冠的ESL吉隆坡站的比赛&#xff0c;spirit战队就并未参加&#xff0…

视频转码实例:把MP4转为MKV视频,一键批量转换的操作方法

在数字媒体时代&#xff0c;视频格式的多样性是不可避免的。经常把MP4格式的视频转换为MKV格式。MKV格式有较高的音频和视频质量&#xff0c;能在其他设备或软件上播放视频。以下是云炫AI智剪如何把MP4视频转为MKV格式的一键批量转换操作方法。 已转码的mkv视频效果缩略图展示…

kubernetes pod 高级

一、pod资源限制 1、什么是pod的资源限制 在Kubernetes集群中&#xff0c;为了使系统能够稳定的运行&#xff0c;通常会对Pod的资源使用量进行限制。 在Kubernetes集群中&#xff0c;如果有一个程序出现异常&#xff0c;并占用大量的系统资源。如果未对该Pod进行资源限制的话…

Git学习笔记(第4章):Git分支

目录 4.1 分支的概述 4.1.1 什么是分支 4.1.2 分支的好处 4.2 查看分支&#xff08;查&#xff09; 4.3 创建分支&#xff08;增&#xff09; 4.4 切换分支 4.5 修改分支&#xff08;改&#xff09; 4.6 合并分支&#xff08;正常合并&#xff09; 4.7 合并分支&#…

CGAL最小生成树、可视化

CGAL 5.4.5 - Surface Mesh: User Manual 1、Kruskal计算最小生成树 #include <CGAL/Simple_cartesian.h> #include <CGAL/Surface_mesh.h> #include <boost/graph/kruskal_min_spanning_tree.hpp> #include <iostream> #include <fstream> #inc…

贝塞尔曲线(Bezier Curve)原理、公式推导及matlab代码实现

目录 参考链接 定义 直观理解 公式推导 一次贝塞尔曲线&#xff08;线性公式&#xff09; 二次贝塞尔曲线&#xff08;二次方公式&#xff09; 三次贝塞尔曲线&#xff08;三次方公式&#xff09; n次贝塞尔曲线&#xff08;一般参数公式&#xff09; 代码实现 参考链接…

群晖NAS搭建WebDav结合内网穿透实现公网访问本地影视资源

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

2024华数杯国际数学建模B题思路+代码+模型+论文

2024华数杯国际数学建模B题思路代码模型论文&#xff1a;1.17上午第一时间更新&#xff0c;详细内容见文末名片 问题B&#xff1a;光伏电 背景 中国的电力构成包括传统的能源发电&#xff08;如煤炭、石油和天然气&#xff09;、可再生能源发电 &#xff08;如水力发电、风能…

OpenGL:关于纹理映射时任意四边形中的插值问题(二)

OpenGL&#xff1a;关于纹理映射时任意四边形中的插值问题-CSDN博客 上次是使用逆双线性插值的方法解决四边形纹理映射时产生的折痕问题。 其实也有点问题&#xff0c;就是双线性插值会使得纹理产生一点扭曲。 不是投影的效果。 想达到纹理投影的效果&#xff0c;可以使用透…

AndroidStudio下载安装教程

下载链接&#xff1a;官方下载 https://developer.android.google.cn/studio?hlzh-cn点击后弹出条款及条件页面&#xff0c;往下滑&#xff0c;勾选同意&#xff0c;然后就点击下载&#xff0c;等待下载完成 下载完成后双击打开&#xff0c;Next 继续Next 选择安装路径&am…

行列转化【附加面试题】

在MySQL中&#xff0c;行列转换是一种常见的操作。它包括行转列和列转行两种情况。 行转列&#xff1a;行转列是将表中的某些行转换成列&#xff0c;以提供更为清晰、易读的数据视图。例如&#xff0c;假设我们有一个包含科目和分数的表&#xff0c;我们可以使用SUM和CASE语句…

C++(13)——string

上篇文章中介绍了中部分函数的用法&#xff0c;本篇文章将继续对其他的函数进行介绍&#xff1a; 1. substr: string substr (size_t pos 0, size_t len npos) const; 函数的两个参数如上述代码所示&#xff0c;此函数的主要作用是根据一个已有的的对象的起始坐标开始&a…

基于python集成学习算法XGBoost农业数据可视化分析预测系统

文章目录 基于python集成学习算法XGBoost农业数据可视化分析预测系统一、项目简介二、开发环境三、项目技术四、功能结构五、功能实现模型构建封装类用于网格调参训练模型系统可视化数据请求接口模型评分 0.5*mse 六、系统实现七、总结 基于python集成学习算法XGBoost农业数据可…

我终于学会的前端技能——代码调试、打断点

在技术的世界里&#xff0c;要用魔法来打败魔法 说来惭愧我做前端已近三年了竟然还没有学会如何调试代码&#xff0c;也就是给自己的代码打上断点一步步看它的运行状态以达到理清代码运行逻辑、排查问题提升开发效率的目的。直到最近我才学会了这一技能&#xff0c;在这之前我…

JSP简单学习

jsp是在html中嵌入java代码 jsp也是在j2ee服务端中的java组件 第一次运行 在第一次运行jsp代码时会经历以下步骤&#xff0c;将jsp转为java代码&#xff0c;将java代码转为class文件。 所以通常会比较慢&#xff0c;编译后就好多了。 四大作用域 requestsessionpageapplica…

CUDA Toolkit 下载,安装,验证

CUDA Toolkit 下载 进cuda官网下载 CUDA Toolkit链接&#xff1a; https://developer.nvidia.com/cuda-downloads 官网默认显示当前的最新版本&#xff0c;这里以安装CUDA Toolkit 12.2 为示例 下载CUDA Toolkit 完成 CUDA Toolkit 安装 开始安装&#xff1a; 点同意&#…

Linux第30步_通过USB OTG将固件烧写到eMMC中

学习目的&#xff1a;在Win11中&#xff0c;使用STM32CubeProgrammer工具&#xff0c;通过USB OTG将固件烧写到eMMC中。 安装软件检查&#xff1a; 1、是否安装了JAVA; 2、是否安装了STM32CubeProgrammer工具; 3、是否安装 了DFU驱动程序; 4、是否安装了“Notepad”软件; …