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

news2024/11/15 15:30:56

颜色线性插值

绘制一条颜色渐变的直线,直线上每一个点的颜色都来自端点颜色的线性插值。线性插值公式为
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反走样算法画的直线,将图片稍微放大就可以看到区别(一个比较粗糙,一个比较光滑)。
在这里插入图片描述

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

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

相关文章

[flutter]GIF速度极快问题的两种解决方法

原因&#xff1a; 当GIF图没有设置播放间隔时间时&#xff0c;电脑上会默认间隔0.1s&#xff0c;而flutter默认0s。 解决方法一&#xff1a; 将图片改为webp格式。 解决方法二&#xff1a; 为图片设置帧频率&#xff0c;添加播放间隔。例如可以使用GIF依赖组件设置每秒运行…

低代码技术杂谈

一、探讨低代码的定义 “Low-Code”是什么&#xff1f;身为技术人员听到这种技术名词&#xff0c;咱们第一反应就是翻看维基百科 或者其他相关技术论文&#xff0c;咱们想看维基百科的英文介绍&#xff1a; A low-code development platform (LCDP) provides a development env…

Docker(七)使用网络

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; Docker 中的网络功能介绍 Docker 允许通过外部访问容器或容器互联的方式来提供网络服务。 一、外部访问容器 容器中可以运行一些网络应用&…

数学建模常见算法的通俗理解(1)

目录 1.层次分析法&#xff08;结合某些属性及个人倾向&#xff0c;做出某种决定&#xff09; 1.1 粗浅理解 1.2 算法过程 1.2.1 构造判断矩阵 1.2.2 计算权重向量 1.2.3 计算最大特征根 1.2.4 计算C.I.值 1.2.5 求解C.R.值 1.2.6 判断一致性 1.2.7 计算总得分 2 神经…

go语言(八)---- map

map的声明方式有以下三种。 package mainimport "fmt"func main() {//第一种声明方式//声明map1是一个map类型&#xff0c;key是String&#xff0c;value是Stringvar myMap1 map[string] stringif myMap1 nil {fmt.Println("myMap1 是一个空map")}//在使…

多测师肖sir___ui自动化测试po框架(升级)

ui自动化测试po框架&#xff08;升级&#xff09; po框架 一、ui自动化po框架介绍 &#xff08;1&#xff09;PO是Page Object的缩写&#xff08;pom模型&#xff09; &#xff08;2&#xff09;业务流程与页面元素操作分离的模式&#xff0c;可以简单理解为每个页面下面都有一…

java数据结构与算法刷题-----LeetCode59. 螺旋矩阵 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 初始&#xff0c;top行执向第一行&#xff0c;bottom行指向最后一…

积分梳状滤波器CIC原理与实现

CIC&#xff08;Cascade Intergrator Comb&#xff09;&#xff1a;级联积分梳状滤波器&#xff0c;是由积分器和梳状滤波器级联而得。滤波器系数为1&#xff0c;无需对系数进行存储&#xff0c;只有加法器、积分器和寄存器&#xff0c;资源消耗少&#xff0c;运算速率高&#…

TypeScript语法总结

JavaScript 与 TypeScript 的区别 TypeScript 是 JavaScript 的超集&#xff0c;扩展了 JavaScript 的语法&#xff0c;因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改&#xff0c;TypeScript 通过类型注解提供编译时的静态类型检查。 TypeScript 可处理已…

GitHub 13.7k star,一款让Windows和macOS瘦身减肥实用工具,免安装+开源+性能高

GitHub 13.7k star&#xff0c;一款让Windows和macOS瘦身减肥实用工具&#xff0c;免安装开源性能高 大家好&#xff01;我是老码农。 今天给大家推荐一款&#xff1a;让Windows和macOS操作系统瘦身减肥的实用工具&#xff0c;czkawka。 这款工具主要干啥事呢&#xff1f;说…

Latex绘图

排查Latex报错 “Command \csubfigure already defined” 这个可以通过添加如下命令&#xff1a; \usepackage{subfig} \usepackage{subfloat} ..... \begin{figure*}[h] \centering \subfloat[subfloat title]{ \label{fig:subfig:a} \includegraphics[scale0.7]{Figs/.....…

MeterSphere本地化部署实践

项目结构 搭建本地环境 安装JDK11&#xff0c;配置好JDK环境&#xff0c;系统同时支持JDK8和JDK11安装IEAD&#xff0c;配置JDK环境配置maven环境,IDEA配置(解压可以直接使用)无限重置IDEA试用期配置redis环境(解压可以直接使用) 配置kafka环境 安装mysql-5.7环境&#xff…

九州金榜|在孩子家庭教育中放手不放任

家庭教育&#xff0c;是每个父母都要面临的事情&#xff0c;也是每个家庭都要经历的&#xff0c;但是在目前的家庭教育中&#xff0c;孩子都是由父母规划&#xff0c;在一定程度上会对孩子的成长产生影响&#xff0c;如何科学家庭教育&#xff0c;九州金榜家庭教育有以下观点&a…

论文阅读笔记AI篇 —— Transformer模型理论+实战 (三)

论文阅读笔记AI篇 —— Transformer模型理论实战 &#xff08;三&#xff09; 第三遍阅读&#xff08;精读&#xff09;3.1 Attention和Self-Attention的区别&#xff1f;3.2 Transformer是如何进行堆叠的&#xff1f;3.3 如何理解Positional Encoding&#xff1f;3.x 文章涉及…

【蓝桥杯EDA设计与开发】立创开源社区分享的关于蓝桥被EDA真题与仿真题的项目分析

立创开源社区内有几个项目分享了往年 EDA 设计题目与仿真题&#xff0c;对此展开了学习。 【本人非科班出身&#xff0c;以下对项目的学习仅在我的眼界范围内发表意见&#xff0c;如有错误&#xff0c;请指正。】 项目一 来源&#xff1a;第十四届蓝桥杯EDA赛模拟题一 - 嘉立…

1432 - 走出迷宫的最少步数-广度优先搜索BFS

代码 #include<bits/stdc.h> using namespace std; char a[51][51]; int r,c; int fx[4]{0,0,1,-1}; int fy[4]{1,-1,0,0}; int tx,ty; struct Node{int x,y,step; }; int bfs(int x,int y){a[x][y]#;queue<Node> q;q.push({x,y,1});while(!q.empty()){Node Curre…

宋仕强论道之再混华强北(三十五)

我是2012年重新回到华强北的&#xff0c;宋仕强说来深圳市第一份工作就在华强北担任一名工程师&#xff0c;和华强北有深厚的感情。我回来后经常混华强北的上层圈子跟老板老板娘们吹牛逼&#xff0c;最初大家看我穿的衣冠楚楚人模狗样的但态度吊儿郎当&#xff0c;理论一套一套…

Hadoop基础知识

Hadoop基础知识 1、Hadoop简介 广义上来说&#xff0c;Hadoop通常是指一个更广泛的概念——Hadoop生态圈。狭义上说&#xff0c;Hadoop指Apache这款开源框架&#xff0c;它的核心组件有&#xff1a; HDFS&#xff08;分布式文件系统&#xff09;&#xff1a;解决海量数据存储Y…

力扣-202. 快乐数解析-弗洛伊德循环查找算法

题目链接 public static void Happy(int n) {int sum 0;int digit 0;for (int i 0; i < 20; i) {while (n ! 0) {digit n%10;sum digit*digit;n/10;}System.out.print(sum " ");n sum;sum 0;}} 使用代码测试一下每一代数字 n 2 : 4 16 37 58 89 145 42 …

如何在Docker下部署MinIO存储服务通过Buckets实现文件的远程上传

&#x1f4d1;前言 本文主要是Linux下通过Docker部署MinIO存储服务实现远程上传的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#…