MFC-彩色渐变反走样直线扫描转换
以下是C++代码
MFC颜色渐变直线扫描转换
根据距离误差项方法构建的基于武悠林算法的彩色渐变反走样直线的MFC代码
要在C++项目中使用时,请将函数头复制一份到头文件中
#include<math.h>
#define Round(x) (int)floor(x+0.5)
#define COL(x) RGB(Round(x*(bR-cRi)+cRi), Round(x * (bG - cGi) + cGi), Round(x * (bB - cBi) + cBi))
bool C**Dlg::antialisingLine(CDC* pDC, Vector2 start, Vector2 end,bool choose/*是否开启颜色渐变*/,
COLORREF backgroundColor/*背景颜色*/)
{
// TODO: 在此处添加实现代码.
//交换起点和终点使正方向朝向第一、二象限;
if (start.y > end.y)
{
Vector2 t=start;
start = end;
end = t;
}
//变量:主位移方向,0代表x为主位移方向,1代表y为主位移方向;
BOOL mainDirect;
//将背景色的R、G、B分量都提出来
int bR, bG, bB;
//将起点、终点的RGB分量提出来
COLORREF startcol, endcol;
if (choose)
{
bR = GetRValue(backgroundColor);
bG = GetGValue(backgroundColor);
bB = GetBValue(backgroundColor);
startcol = start.color2+RGB(0,0,0);
endcol = end.color2+RGB(0,0,0);
}
else
{
bR = 255;
bG = 255;
bB = 255;
startcol = RGB(0,0,0);
endcol = RGB(0,0,0);
}
int sR, sG, sB;
int eR, eG, eB;
sR = GetRValue(startcol);
sG= GetGValue(startcol);
sB= GetBValue(startcol);
eR= GetRValue(endcol);
eG = GetGValue(endcol);
eB = GetBValue(endcol);
//分别计算起点和终点的颜色差值分量
int dR = eR - sR;
int dG = eG - sG;
int dB = eB - sB;
//cout << "R差值:" << dR << "G差值:" << dG << "B差值:" << dB << endl;
//设置主位移颜色差值单元(在判断出主位移后使用)
float ddR, ddG, ddB;
//1.给出起点和终点,判断主位移方向
float dy = end.y - start.y;
//cout << "dy:" << dy << endl;
float dx = end.x - start.x;
float abDx = fabs(dx);
//cout << "abDX:" << abDx << endl;
if ((dy - abDx) < 0.0)
{
//说明Y轴增量没有x轴增量大,主位移方向为x轴正方向
//cout << "主位移方向确定为x轴正方向" << endl;
mainDirect = 0;
//设置主位移方向上的颜色差值单元量
ddR = (float)dR / abDx;
ddG = (float)dG / abDx;
ddB = (float)dB / abDx;
}
else
{
//相反地,主位移方向为y轴正方向
//cout << "主位移方向确定为y轴正方向" << endl;
mainDirect = 1;
//设置主位移方向上的颜色差值单元量
ddR = (float)dR / dy;
ddG = (float)dG / dy;
ddB = (float)dB / dy;
}
//2.针对主位移方向计算斜率,确保不出现分母为0的情况
float k=0.0;
//初始化距离误差项e
float e = 0.0;
//初始化绘制起点
int yi = start.y;
int xi = start.x;
//初始化绘制颜色值;
float cRi = sR*1.0;
float cGi = sG*1.0;
float cBi = sB*1.0;
switch (mainDirect)
{
case 0:
//主位移方向为x轴,因为正方向朝向第一、二象限,
//所以当主位移方向是x轴时需要分k<0和k>0两种情况
k = dy / dx;
cout << "主位移为x轴"<<"未变换k:"<<k << endl;
if (k == 0.0)
{
//水平线
if(choose)
{
do
{
pDC->SetPixelV(xi, yi, COL(e));
cRi = cRi + ddR;
cGi = cGi + ddG;
cBi = cBi + ddB;
start.x>end.x?xi--:xi++;
//cout << "xi:" << xi << endl;
//截取e的小数部分,使e永远小于1
} while (start.x > end.x ? xi >= end.x: xi <= end.x);
}
else
{
pDC->MoveTo(start.toCPoint());
pDC->LineTo(end.toCPoint());
}
return true;
}
else if (k < 0.0)
{
//-1<k<0
k = -k;
//cout << "变换之后的k:" << k << endl;
do
{
pDC->SetPixelV(xi,yi,COL(e));
pDC->SetPixelV(xi, yi + 1, COL((1-e)));
e += k;
if (e >= 1.0)
{
e -= 1.0;
yi += 1;
}
cRi = cRi + ddR;
cGi = cGi + ddG;
cBi = cBi + ddB;
xi--;
//cout << "xi:" << xi << endl;
//截取e的小数部分,使e永远小于1
} while (xi>=end.x);
return true;
}
else
{
//1>k>0
//cout << "变换之后的k:" << k << endl;
do
{
pDC->SetPixelV(xi, yi, COL(e));
pDC->SetPixelV(xi, yi + 1, COL((1 - e)));
e += k;
if (e >= 1.0)
{
e -= 1.0;
yi += 1;
}
cRi = cRi + ddR;
cGi = cGi + ddG;
cBi = cBi + ddB;
xi++;
//截取e的小数部分,使e永远小于1
} while (xi <= end.x);
return true;
}
break;
case 1://主位移方向为y轴
k = dx / dy;
//cout << "主位移为y轴" << "未变换k:" << k << endl;
if (k == 0.0)
{
if (choose)
{
do
{
pDC->SetPixelV(xi, yi, COL(e));
cRi = cRi + ddR;
cGi = cGi + ddG;
cBi = cBi + ddB;
yi++;
//cout << "xi:" << xi << endl;
//截取e的小数部分,使e永远小于1
} while (yi<=end.y);
}
else
{
pDC->MoveTo(start.toCPoint());
pDC->LineTo(end.toCPoint());
}
//垂直线
return true;
}
else if (k < 0.0)
{
//-1>k>负无穷
k = -k;
cout << "变换之后的k:" << k << endl;
do
{
pDC->SetPixelV(xi, yi, COL(e));
pDC->SetPixelV(xi-1, yi, COL((1 - e)));
e += k;
if (e >= 1.0)
{
e -= 1.0;
xi -= 1;
}
cRi = cRi + ddR;
cGi = cGi + ddG;
cBi = cBi + ddB;
yi++;
//截取e的小数部分,使e永远小于1
} while (yi <= end.y);
return true;
}
else
{
//正无穷>k>1
//cout << "变换之后的k:" << k << endl;
do
{
pDC->SetPixelV(xi, yi, COL(e));
pDC->SetPixelV(xi + 1, yi, COL((1 - e)));
e += k;
if (e >= 1.0)
{
e -= 1.0;
xi += 1;
}
cRi = cRi + ddR;
cGi = cGi + ddG;
cBi = cBi + ddB;
yi++;
//截取e的小数部分,使e永远小于1
} while (yi <= end.y);
return true;
}
break;
default:
return false;
break;
}
//cout << "dy:" << dy << ",dx:" << dx << ",k:" << k << endl;
return false;
}
其中需要使用二维向量(点)类
Vector2.h
#pragma once
#include<atltypes.h>
#include<math.h>
#ifndef Round(d)
#define Round(d) (int)floor(d+0.5)
#endif //Round(d)
class Vector2
{
public:
float x=0.0f;
float y=0.0f;
COLORREF color2;
Vector2();
Vector2(float x1,float y1,COLORREF col):x(x1),y(y1),color2(col){}
Vector2(const Vector2& v):x(v.x),y(v.y),color2(v.color2){}
CPoint toCPoint();
Vector2& operator =(const Vector2& v);
~Vector2();
Vector2.cpp
#include"Vector2.h"
Vector2::Vector2()
{
}
Vector2::~Vector2()
{
}
CPoint Vector2::toCPoint()
{
return CPoint(Round(x),Round(y));
}
Vector2& Vector2::operator =(const Vector2& v)
{
x=v.x;
y=v.y;
color2=v.color2;
return *this;
}